swift-4.0.2-RELEASE来てた。String は StringProtocol だけど Number は Numeric なんですね… https://developer.apple.com/documentation/swift/numericStringProtocol 以外の XxxProtocol って何があります?IteratorProtocol 普通にわすれてたw NSObjectProtocol なんてあるのかぁ(白目public protocol NSObjectProtocol { ってなってるのに、実際の動きは public protocol NSObjectProtocol: class { なんじゃあないのっていうのが各所で浮き出てくる (edited)Iterator っていう 名前衝突を避けたくてそうなった感があるけどね・・・@objcつけたらclass矯正されるのと同じ感じですかね@objc明示ルール出来たのにNSObjectProtocolはそうじゃないっていうのもねinherits、何かの型がprotocolに準拠している場合は conforms、多分これで問題ないかと…?Int は型だから protocol に Conforms To ですねStatus を abstract class で定義できたらなぁとすごい思うstruct StackArray<value Size: Int> { ... }var a = StackArray<2>() a.0 // ok a.1 // ok a.2 // compile error (edited)enum Status { case NotReady case Ready } class Something<value T: Status> { /*中身は同じでOK*/ } (edited)value T: Status になってるのか。 (edited)Status が protocol じゃダメなんだっけ? sealed にできない?- Now you can define a “dependent type”, for example ModuloInteger<P>, where P is the integer value that defines the type. - Like this, you’ll have: —> MI<2>: {0, 1}, where 1 + 1 = 0. —> MI<3>: {0, 1, 2}, where 1 + 1 = 2, and 2 • 2 = 1Status が protocol でもダメってことはないですが、Something<NotReady>.createInstance() で書かないといけないのがイケてないですねVector<2> とか Matrix<4, 4> とかやりたい。struct MultiArray<T, let Dimensions: Int> { // specify the number of dimensions to the array subscript (indices: Int...) -> T { get { require(indices.count == Dimensions) // ... } } (edited)struct Real { ... } extension Real : ConstructibleFrom<Float> { init(_ value: Float) { ... } } extension Real : ConstructibleFrom<Double> { init(_ value: Double) { ... } } サンプルも Rust の From trait と似てるenumでstateパターン、無理やりRawValueに振る舞いを実装して見た https://gist.github.com/norio-nomura/65db97c4786851bc368a8d68834fb31b (edited)RawRepresentable で実装where T: Ready で書くと問題ないけど、where T == Ready で書くと Something.createInstance() の直後でも変換の補完で .shout() が出るのなんで?(もちろんコンパイルエラーにはなるけど…)$ swift generate.swift で実行しているだけなんや。%{ let intTypes = [8,16,32,64] }% % for intType in intTypes { % for sign in ["", "U"] { /// Extension that adds a few additional functionalities to ${sign}Int${intType} extension ${sign}Int${intType} { /// Returns a ${sign}Int${intType} with all ones % if sign == "" { public static var allOnes: Int${intType} { return Int${intType}(bitPattern: UInt${intType}.max) } % } else { public static var allOnes: UInt${intType} { return UInt${intType}.max } % } } % } % }-alpha とか -beta つけるのオススメ。end とか Python じゃないし。-swift-version 3を渡してるかどうかは #if swift(>=3.2.2) で判定。 (edited)[omochi@omochi-iMac gysb (master *+=)]$ cat Examples/include.swift.gysb %! include_code("libs/*.swift") % aaa=${aaa()} bbb=${bbb()} [omochi@omochi-iMac gysb (master *+=)]$ swift run gysb Examples/include.swift.gysb aaa=999 bbb=777%! と include_code を追加したのでなんとかなるmaster *+= ってなんや%! swift_package("Package.swift") とか定義しておくと SPM の executable として実行するような機能を作ったら対応できそう。%{...}の中にimportは書けないのか[omochi@omochi-iMac gysb (master=)]$ swift run gysb --compile Examples/include.swift.gysb func write(_ s: String) { print(s, terminator: "") } func aaa() -> Int { return 999 } func bbb() -> Int { return 777 } write("aaa=") write(String(describing: aaa())) write("\n") write("bbb=") write(String(describing: bbb())) write("\n").gysbインプットから.swiftのStringを作れるAPIがあると、swift testの度に.swiftを生成する事ができる様になります。 (edited)#comment(lib, "GL.h") ってかいてリンク指定できるみたいな。 (edited)*.cをパッケージ内に持ってて、SwiftPMにClangモジュールとしてビルドしてもらってます。Run Script Phaseを使えるからCLIでいいけど、SwiftPMはビルドプロセスに入れられないのがネックだね。vapor build の手前に処理を差し込む方法ないのって問い合わせたらねえって言われた (edited)vapor cloud deploy するとリモートでチェックアウトして vapor build が動くんだけどその手前でコードジェネレータ動かしてもらわないと成果物コミットしてないから当然コンパイル通らないPackage.swiftの内容を切り替え、GYSB=1 swift testでコード生成し、swift testで生成したコードを利用する方法を思いついた。swift test --filter Generateとテストするモジュールを制限しても全てをビルドしようとするから、未生成なコードに依存する部分がビルド出来なくてダメだった。// swift-tools-version:4.0 import PackageDescription import Foundation let package: Package if ProcessInfo.processInfo.environment["GYSB"] != nil { package = Package( name: "Generate", dependencies: [ .package(url: "https://github.com/omochi/gysb.git", .branch("master")), ], targets: [ .testTarget(name: "Generate", dependencies: ["GysbKit"], path: "Tests/GenerateTests") ] ) } else { package = Package( name: "Example", products: [ .library(name: "Example", targets: ["Example"]), .library(name: "Generated", targets: ["Generated"]), ], targets: [ .target(name: "Example", dependencies: ["Generated"]), .target(name: "Generated", dependencies: []), .testTarget(name: "ExampleTests", dependencies: ["Example"]), ] ) }$ tree . ├── Package.resolved ├── Package.swift ├── README.md ├── Sources │ ├── Example │ │ └── BuildPhase.swift │ └── Generated │ └── vector.swift └── Tests ├── ExampleTests │ └── ExampleTests.swift ├── GenerateTests │ └── GenerateVectorTests.swift └── LinuxMain.swift こんな感じ (edited)Package.swiftでYamsをビルドして、それを.gysbの中でインポートしようとしてるのだけど、うまくいかないな。Test Case '-[GysbWithYamsTests.GysbWithYamsTests testExample]' started. process execution failure path=[/usr/bin/swift] arg[0]=[/var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/vector_49IokLMk.swift] arg[1]=[-L] arg[2]=[/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug] statusCode=[1] stderr= /var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/vector_49IokLMk.swift:4:9: error: no such module 'Yams' import Yams ^ Test Case '-[GysbWithYamsTests.GysbWithYamsTests testExample]' passed (0.438 seconds).$ /usr/bin/swift /var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/vector_49IokLMk.swiftreturn try execCapture(path: swiftPath, arguments: [path, "-L", "/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug"]) (edited) -F <value> Add directory to framework search path-l も必要だったかはよくわからない-I…,-L…,-F…つけても、YamsのPackage.swiftでライブラリtypeを.staticや.dynamicにして-lYamsつけてもダメだ。 path=[/usr/bin/swift] arg[0]=[/var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/vector_NwwoI7hu.swift] arg[1]=[-I] arg[2]=[/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug] arg[3]=[-F] arg[4]=[/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug] arg[5]=[-L] arg[6]=[/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug] arg[7]=[-lYams] statusCode=[1] stderr= /var/folders/kt/2mwy9b_56_7993x190pl_1fh0000gn/T/vector_NwwoI7hu.swift:4:9: error: no such module 'Yams' import Yams (edited).dynamicにして、以下のオプションをswiftに渡したらいけた。 return try execCapture(path: swiftPath, arguments: [ "-I", "/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug", "-L", "/Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug", "-lYams", path, ])% import Foundation % import Yams % guard let yaml = try Yams.compose(yaml: String(contentsOf: URL(fileURLWithPath: "TestResources/vector/vector.yml"))) else { fatalError() } % let vars = yaml.array().flatMap { $0.string } % for n in 2...4 { struct Vector${n} { % for i in 0..<n { var ${vars[i]}: Float % } } % }swift run gysb が通る状態?// swift-tools-version:4.0 import PackageDescription let package = Package( name: "GysbWithYams", dependencies: [ .package(url: "https://github.com/omochi/gysb.git", .branch("master")), .package(url: "https://github.com/jpsim/Yams.git", .branch("master")), ], targets: [ .testTarget( name: "GysbWithYamsTests", dependencies: ["GysbKit", "Yams"]), ] )
class GysbWithYamsTests: XCTestCase { func testExample() { do { let driver = Driver.init(path: "TestResources/vector/vector.swift.gyb") let actual = try driver.render(to: .render) print(actual) } catch { print(error) } } static var allTests = [ ("testExample", testExample), ] } (edited)libYams.aかlibYams.dylibが無いとダメですね。type: .staticでも本当はいけると思うのですが、swiftcがクラッシュしてしまいダメでしたが。.o達を直接リンクします。 (edited)swift test -vとかしてみるとコンパイラの起動オプションを見られます。type: .dynamicにするとswift build --static-swift-stdlibとかしてもそれらのライブラリはダイナミックリンクされるみたいだから、今後は使い勝手が悪くなると避けられるんじゃないかな? (edited).dynamicなライブラリを同じパッケージ内のexecutableターゲットから使う場合は問題ないのですが、依存しているパッケージから使った場合、それらはフルパスでリンクされてしまい、ポータブルなexecutableではなくなってしまいます。 $ otool -L ./.build/x86_64-apple-macosx10.10/debug/gysbClient ./.build/x86_64-apple-macosx10.10/debug/gysbClient: /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 1445.12.0) /Users/norio/github/GysbWithYams/.build/x86_64-apple-macosx10.10/debug/libGysbKit.dylib (compatibility version 0.0.0, current version 0.0.0) /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0) /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1252.0.0) (edited)prefix operator > prefix func >(value: String) { print(value) } let intTypes = [8, 16, 32, 64] for intType in intTypes { for sign in ["", "U"] { >""" /// Extension that adds a few additional functionalities to \(sign)Int\(intType) extension \(sign)Int\(intType) { /// Returns a \(sign)Int\(intType) with all ones """ if sign == "" { >""" public static var allOnes:Int\(intType) { return Int\(intType)(bitPattern: UInt\(intType).max) } """ } else { >""" public static var allOnes:UInt\(intType) { return UInt\(intType).max } """ } >""" } """ } } (edited)%{ intTypes = [8,16,32,64] }% % for intType in intTypes: % for sign in ['','U']: /// Extension that adds a few additional functionalities to ${sign}Int${intType} extension ${sign}Int${intType} { /// Returns a ${sign}Int${intType} with all ones %if sign == '': public static var allOnes:Int${intType} { return Int${intType}(bitPattern: UInt${intType}.max) } %else: public static var allOnes:UInt${intType} { return UInt${intType}.max } %end } %end %endManifestoGeneratorとか出来てる!w https://github.com/omochi/gysb/blob/master/Sources/GysbSwiftConfig/ManifestoGenerator.swift%! swift_config("gysb_swift_config.json") %{ import Foundation import Yams let yamlPath = URL.init(fileURLWithPath: "data.yml") let yamlStr = try! String(contentsOf: yamlPath, encoding: .utf8) let yaml = try Yams.compose(yaml: yamlStr)! let fields: [String] = yaml.array().map { $0.string! } }% struct Data { % for field in fields { var ${field}: String % } }{ "packageDependencies": [ { "url": "https://github.com/jpsim/Yams.git", "requirement": { "identifier": "0.5.0", "type": "exact" } }, ], "targetDependencies": [ { "name": "Yams" } ] }%! swift_config() の指定は1ファイルだけがする。%! swift_config("gysb_swift_config.json")gysb.json はどこにあるんだ?ってなっちゃうんですよね%! import("https://github.com/jpsim/Yams.git") とかするとswift_config()に渡すjson相当のものが自動で生成される様にするとか。%! import("https://github.com/jpsim/Yams.git") とかするとswift_config()に渡すjson相当のものが自動で生成される様にするとか。 これの問題点は、パッケージ名からターゲット名がわからないことimport 使えるんだっけ?libSwiftPMが気軽に使えれば「リポジトリからPackage.swiftを解釈して〜」とか簡単に出来そうなのに… https://github.com/apple/swift-package-manager/blob/master/Package.swift#L19%! swift_config("gysb_swift_config.json")brew install gysbできる様になると良いね。%! swift_config 以外に %! include_code っていうマクロ命令もあってswift_config 書く場合と同じでgysb Sources/Foo/*.gysb Sources/Bar/*.gysbgysb src/ で再帰的にgysb さがすの??gysb -r src/ とか明示的にした方が良さそうな気も。gysb.josn も全部適用で良さそう。 (edited)gysb Sources/Foo/*.gysb Sources/Bar/*.gysb みたいなことがしたいんじゃないの?swift_config を導入せずに gysb.json を置く方式にするのであれば、一つのディレクトリの中で設定を切り替えることはできないという意味です。Sources/Foo/gysb.json Sources/Bar/gysb.jsonSouces/gysb.json と Sources/Foo/gysb.json をマージ、 Souces/gysb.json と Sources/Bar/gysb.json して 2 回実行 Souces/gysb.json Sources/Foo/gysb.json Sources/Bar/gysb.jsonFoo/gysb.json 等に記述することを想定)Foo, Bar 以下のすべての gysb ファイルに対して 1 回で実行 Souces/gysb.json%! swift_conifig はやめてディレクトリ遡り探索の gysb.json にしようと思います%! という複雑性を持ち込まなくてよさそう。% func foo() { FooFooFoo % } % for _ in 0..<3 { % foo() % }FooFooFoo FooFooFoo FooFooFoofunc taxRate() -> Float { return 1.08 }%{ func taxRate() -> Float { return 1.08 } }metalib.swift.gysb とかになる。Sources/foo/a.swift.gysb // こいつが それを読みに行く Sources/foo/metalib/metalib.swift.gysb$ gysb --source-dir Sources を実行すると・・・Sources/foo/metalib/metalib.swift.gysb が 処理対象になって、 自分を自分の上部にincludeしようとして、無限ループして壊れる。func taxRate() みたいな、ちょっとしたやつ。%! 的な構文は避けられなさそう。%! から逃げられないですね%! include("path/to/file") の行をそのファイルの中身で展開するだけ。{% include footer.html %}{% include {{ page.my_variable }} %}% for i in 0..<10 { %! include("file\(i).gysbi") % }%! のマクロ言語はテンプレート処理系の前段にあるとしていますinclude を関数として実装できないかな?write するgysbi ファイルに対して gysb を実行して得られた文字列を挿入すれば。%! も排除できる。brewのバイナリ配布、sourceryがSwiftPMでビルドしたものを使ってる。 https://github.com/Homebrew/homebrew-core/blob/master/Formula/sourcery.rbbottles do ... end にバイナリの置き場所書けば対応で、省略すればインストール先でビルド必要な認識でした。 (edited)[swift-evolution] update on forum Ted Kremenek via swift-evolution The decision to move to a forum was announced a while ago, and it hasn’t appeared yet. I think we will be making the move soon and I wanted to provide some reasons why it was delayed and what comes next. ... My hope is that process will start in December.yaml ならいけるかもしれませんが、 gysb の実行に YAML パーサが必要になって依存が生まれてしまいそう・・・ 一応書いておくと、YamsはCodableをサポートしたYAMLパーサです。Yams自身には外部ライブラリ依存はなくて、利用実績としてはSwiftLintが.swiftlint.ymlのパースに使っています。$(brew --repository homebrew/core) git remote add omochi https://github.com/omochi/homebrew-core.git したら、次のコマンドでformula作成: brew create https://github.com/omochi/gysb/archive/0.8.6.tar.gz して、出来たgysb.rbのdepends_on, def install, test doを https://github.com/Homebrew/homebrew-core/blob/master/Formula/sourcery.rb 辺りを参考に設定して、 brew install --verbose --debug gysb でインストールテストして、 cd $(brew --repo homebrew/core) git checkout -b gysb git add Formula/gysb.rb git commit git push https://github.com/omochi/homebrew-core/ gysb してPR、って感じかな?Makefileとか不要。class Gysb < Formula desc "Generate your swifty boilerplate" homepage "" url "https://github.com/omochi/gysb/archive/0.8.6.tar.gz" sha256 "139fd7225442c74e943b32716158a3ea5bd438241372a3cf913fd5313793248e" depends_on :xcode => ["9.0", :build] def install system "swift", "build", "--disable-sandbox", "-c", "release", "-Xswiftc", "-static-stdlib" bin.install ".build/x86_64-apple-macosx10.10/release/gysb" end test do # `test do` will create, run in and delete a temporary directory. # # This test will fail and we won't accept that! For Homebrew/homebrew-core # this will need to be a test that verifies the functionality of the # software. Run the test with `brew test gysb`. Options passed # to `brew install` such as `--HEAD` also need to be provided to `brew test`. # # The installed folder is not in the path, so use the entire path to any # executables being tested: `system "#{bin}/program", "do", "something"`. system "true" end endtest doにsystem "true"とか書いたけど、そこは真面目に書き換えないといけない。sourcery --versionで返すかどうか、かな。+struct ParameterizedStruct<T> { + mutating func takesFunctionWithGenericReturnType(_ f: (Int) -> T) {} +} これがArrayに相当してるのかgit tag --contains cf9a09e18dba7a7fe0506381589fbf0f4bb99a98 で何も出ない。swift-DEVELOPMENT-SNAPSHOT-2017-11-21-a出てる。func processPo<X: ConstPo>(po: X, process: (X.Element) -> Void) { これでokconst の場合と違って、型ごと CostoPo を満たさないといけないの微妙そう。struct じゃダメ? Swift の class は二級市民だと思ってる。View に対応した ViewModel を struct で作って渡すとか?View 自体を操作する関数だとダメだけど。const にしたいくらいだから View から情報をとりたいだけに見える)enum Hoge { case fuga(Int) case piyo(Int) var count: Int { switch self { case .fuga(let count), .piyo(let count): // <- ここ return count } } }let count だからいける?protocol ProtocolA {} enum Hoge { case fuga(ProtocolA) case piyo(ProtocolA) var count: ProtocolA { switch self { case .fuga(let count), .piyo(let count): return count } } }Playground execution failed: error: MyPlayground.playground:5:24: error: matching a protocol value in multiple patterns is not yet supported; use separate cases instead case .fuga(let count), .piyo(let count): ^protocol ProtocolA {} enum Hoge<T: ProtocolA> { case fuga(T) case piyo(T) var count: T { switch self { case .fuga(let count), .piyo(let count): return count } } }let a: Int? = 42 if case let a? = a { print(a) } int *a = ...; *a = 42; って書くのと似てるよね。 (edited)*a が int 型というのと、 a? が Int 型というのが。a? は Int 型ではないですよねa? は Optional<Int> だからこそ a の部分だけが Inta? は Int? で a が Int か。*a が int で a は int * 。protocol ProtocolA {} enum Hoge<T: ProtocolA> { case fuga(T) case piyo(T) func value<T>() -> T { switch self { case .fuga(let value), .piyo(let value): return value } } }
error: MyPlayground.playground:6:20: error: cannot convert return expression of type 'T' to return type 'T' return value ^~~~~ as! Ttypealias Tuple = (Int, String) enum Hoge { case fuga(Int) case piyo(Tuple) var value: Int { switch self { case .fuga(let value), .piyo((let value, _)): return value } } } case let [first, second, third]: みたいな。error: MyPlayground.playground:6:20: error: cannot convert return expression of type 'T' to return type 'T' return value ^~~~~ as! T これは真っ当なエラーでは…Token と tok と Tok が出てきて、Tok の定義が全然見つからないと思ったら Token 型のフィールド名が Tok だった・・・tok は enumsnake_case_ ですね、他のC++プロダクトをそんなに読んでないのでわからないですがCMake -G XcodeTok でジャンプできたぞw--release-debuginfo --xcode でビルドしたらclang: error: no such file or directory: '/Users/omochi/work/swift-source/build/Xcode-RelWithDebInfoAssert/cmark-macosx-x86_64/src/Debug/libcmark.a' と出ていて (edited)/Users/omochi/work/swift-source/build/Xcode-RelWithDebInfoAssert/cmark-macosx-x86_64/src/RelWithDebInfo/libcmark.a--release-debuginfo なのに cmark は --debug で参照しちゃっててうまくいってないみたいなんですけど--xcode は作業用、 ninja でビルド するのが良いのか? release-debuginfo があまりメンテナンスされていないので、 release にするのが良いのか? とか、どうなんでしょう--xcode のせいなのか、そうでないのか調べるために ninja でもやってみます。 /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/bin/swiftc -apinotes -yaml-to-binary -o /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/lib/swift/macosx/x86_64/ScriptingBridge.apinotesc -target x86_64-apple-macosx10.9 /Users/omochi/work/swift-source/swift/apinotes/ScriptingBridge.apinotes /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/bin/swiftc -apinotes -yaml-to-binary -o /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/lib/swift/macosx/x86_64/ScriptingBridge.apinotesc -target x86_64-apple-macosx10.9 /Users/omochi/work/swift-source/swift/apinotes/ScriptingBridge.apinotes 出力先 /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/lib/swift/macosx/x86_64 が存在してなかったが、 /Users/omochi/work/swift-source/build/Xcode-ReleaseAssert/swift-macosx-x86_64/Release/lib/swift は存在していたので、 mkdir してやったら、いけました。class ViewBindingHelper<Model> { ... } protocol ViewBindingHelperUser { associatedtype Model var helper: ViewBindingHelper<Model> { get } } extension ViewBindingHelperUser { 追加される機能 }class ProductListTableView : NSTableView, ViewBindingHelperUser { let helper: ViewBindingHelper<ProductList> = .init() } (edited)User の方のプロトコルコンフォーマンスは解除して、 .helper.method でヘルパ名をネームスペース代わりにするしか無さそう。protocol MyViewProtocol { var button: Button { get } } protocol HasMyViewProtocol: MyViewProtocol { associatedtype MyView: MyViewProtocol var myView: MyView { get } } extension HasMyViewProtocol { var button: Button { return myView.button } }extension MyViewProtocol に置けば全部使えるようになる-swift-version 3を使うとSwift 3.3になるぽい。 $ TOOLCHAINS=org.swift.4120171207a swift -swift-version 3 Welcome to Apple Swift version 4.1-dev (LLVM 67b9a8e8c2, Clang e617c83242, Swift 65b4172032). Type :help for assistance. 1> #if swift(>=4.1) 2. let versions = "swift-4.1" 3. #elseif swift(>=4.0.3) 4. let versions = "swift-4.0.3" 5. #elseif swift(>=4.0.2) 6. let versions = "swift-4.0.2" 7. #elseif swift(>=4.0) 8. let versions = "swift-4.0" 9. #elseif swift(>=3.3) 10. let versions = "swift-3.3" 11. #elseif swift(>=3.2.3) 12. let versions = "swift-3.2.3" 13. #elseif swift(>=3.2.2) 14. let versions = "swift-3.2.2" 15. #else // if swift(>=3.2) 16. let versions = "swift-3.2" 17. #endif 18. versions: String = "swift-3.3" 18> (edited)subject.value() がthrowsなのってなんでなんだろAVAudioFile もなぜか AVAudioFramePosition は Int64 なのに AVAudioFrameCount は逆に UInt32 しかないという不可解な現象 https://qiita.com/lovee/items/8bdf7b58d96d683d31b9AUAudioFrameCount で自分が上げたのは AVAudioFrameCount なんですよな…This alias is type `uint32_t` for impedance-matching with the pervasive use of `UInt32` in the Audio Toolbox framework and the C Audio Unit framework APIs, as well as the `AVAudioFrameCount` data type. (edited)var length: AVAudioFramePosition The number of sample frames in the file. typealias AVAudioFrameCount A number of audio sample frames. この説明がすでに色々理不尽な気が…(CのAPIに合わせてるのなら逆にじゃあなぜCではcountだけが32bitなのか…ComponentResult AudioUnitRender( AudioUnit ci, AudioUnitRenderActionFlags* ioActionFlags, const AudioTimeStamp* inTimeStamp, UInt32 inOutputBusNumber, UInt32 inNumberFrames, AudioBufferList* ioData ) inNumberFrames The number of frames to be rendered. (edited)SInt32 startBufferOffset これだけ読むとやはりCでは両方32bitにしてるけどAVFoundationがなぜかpositionだけ64bitにしてるんですよね… (edited)UInt32 bufferOffset; bufferOffset Where in the current buffer the event should occur (edited)GL_PROJECTION // Int32 glMatrixMode(GLenum(GL_PROJECTION)) // Obj-C (C) ではそのまま渡せた (edited)static var GL_PROJECTION: GLenum ってオーバレイ用意してほしいですね。#define だったマクロがそのまま Int32 としてポーティングされてしまっている#defineの数値リテラル?はInt32になるよね (edited)#include <stdio.h> #define BIG_NUMBER (0xffffffffffffffff) void printHex(unsigned long long number) { printf("%llx\n", number); } int main(void) { printHex(BIG_NUMBER); return 0; }#define NAME "aaa" みたいなのもありえるので#define は型を判定してるのかな?AVFoundation.framework/Frameworks/AVFAudio.framework/Headers/AVAudioTypes.h
/*! @typedef AVAudioFrameCount @abstract A number of audio sample frames. @discussion Rationale: making this a potentially larger-than-32-bit type like NSUInteger would open the door to a large set of runtime failures due to underlying implementations' use of UInt32. TODO: Remove rationales. */ typedef uint32_t AVAudioFrameCount;TODO: Remove rationales. は具体的に何を指しているのか… int が double に暗黙の型変換されてて、 double c = a / b; ( a と b が Android の API のコールで int が返される)の精度が落ちてしまっている事例が社内で発覚した。やっぱり数値間ですら暗黙の型変換を許さない Swift の方向性は正しかったんだ〜/ 書く時はトラウマが呼び起こされてミスしない体になったc の型を書かずに let にしていた結果、 Int のまま以降の行まで型推論が伝搬していって、/ 書く時は周囲に型をだいぶ明示的に書きたくなるlet t = 1 / 2 ... なんか処理 ... TimeInterval(t)/ は常に実数除算への昇格で、 整数のあまり切り捨て除算は別の演算子になってることもあるね。$ python Python 3.6.1 (default, Apr 19 2017, 14:30:24) [GCC 4.2.1 Compatible Apple LLVM 8.1.0 (clang-802.0.41)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> 3 / 2 1.5 >>> 3 // 2 1// があった気がしてたけどpythonか。JSONEncoderのconvertToSnakeCase はmyURLPropertyをmy_url_propertyに変換するのだけれど、JSONDecoderのconvertFromSnakeCaseはmy_url_propertyをmyUrlPropertyへ変換するので、デコードに失敗する。 https://bugs.swift.org/browse/SR-6629convertFromSnakeCaseの実装がまずい。既存CodingKeysのstringValueのlowercasedとJSONのキーから_を削除した文字列を比較して、一致するCodingKeysメンバを決定しないといけない。 (edited)Stringに汎用のsnake_casedプロパティとかあった方が良さそう。CodingKeys の stringValue から、 encoder側の convertToSnakeCase と同じ変換をかけてから そのキーで JSON のバリューを読めば、ストレートな処理になりませんか? 今の実装のconvertFromSnakeCaseが色々な表記ゆれをサポートしてるせいで、その方法で上位互換にするのは無理かも。 (edited)YAMLDecoderで試しに実装してみた。 https://github.com/jpsim/Yams/pull/92JSONDecoderの実装は無駄に凝りすぎだと思う。typedef NS_ENUM(NSInteger, State) { StateHoge = 0, StateHuga = 1, }; Swift: let state = State(rawValue: 100)! switch state { case .hoge: print("hoge") // ★↑これが実行される case .huga: print("huga") }State(rawValue: 100) が nil にならないところが Swift 的に変で、そこのチェックが漏れてるのかもしれませんね。state.rawValue は 100 ですか? 0 ですか?switch で何が起こるかは仕様として決まってないんじゃないかと思います。#include <Foundation/Foundation.h> typedef NS_ENUM(NSInteger, State) { StateHoge = 0, StateHuga = 1, }; main.swift public func foo(state: State) -> Int { switch state { case .hoge: return 1 case .huga: return 2 } } let s = State(rawValue: 100)! print(foo(state: s)) 実行 $ swift -import-objc-header enums.h main.swift 1 $ swift -O -import-objc-header enums.h main.swift 2 (edited)-O 有無で結果が違うのはちょっと受け入れられない。Numeric って ExpressibleByIntegerLiteral を継承してるのに Int のイニシャライザに Numeric を受けるやつないのか…?// Integer literals are limited to 2048 bits. というコメントが。 https://github.com/apple/swift/blob/0cf1b52452f56b3bbdf2f2305cc10fef42bdff8b/stdlib/public/core/Policy.swift#L99 (edited)Numeric が ExpressibleByIntegerLiteral なのはよくわかんないですよね。行列とかで使えなくなっちゃいますし。Numeric よりも、群・環・体 https://qiita.com/taketo1024/items/733e0ecf12da359db729 みたいなプロトコルほしいですよね。Addable, Multipliable とかの方がプログラミング的には使い勝手がいいのかも?BinaryIntegerとFloatingPointで分けて実装してるのが一本化できるString って subscript { set } ができないからイミュータブルなのかと思ってたけど違った。 1> var s = "ABC" s: String = "ABC" 2> s.removeLast() $R0: Character = { _representation = smallUTF16 { smallUTF16 = 67 } } 3> print(s) ABsubscript { set } ができないのは、 Character が何バイトか定まらないから O(1) で実現できないからか。subscript { set } を実現できない。append とか removeLast とかって MutableCollection についてるのかと思ってたけど違った。で、 subscript { set } がないから String は MutableCollection じゃないだろう→ append や removeLast もないだろうと思って勘違いしてた。 https://developer.apple.com/documentation/swift/mutablecollection (edited)String でも平均 O(1) で実現できて問題ないのか。 (edited)faillthrough のユースケース?それとも^のコードですか?func tokenize(source: String) -> [Token] { let state = State(input: source) for character in state.input { switch state.mode { case .plain: switch character { case "'": state.mode = .symbol case "\"": state.mode = .string case "\n": state.mode = .newline state.storage = "" case "(", ")", ":": state.tokens.append(Token(type: .token, value: String(character))) case " ": break default: state.mode = .token state.storage = String(character) }protocol ValueProducer { associatedtype Value var value: Value { get } } ↑これ自作してさprotocol ValueProducer : ObservableConvertible { associatedtype Value var value: Value { get } }#if _runtime(_ObjC)でのStringのhashValueはそもそも文字列全体を使わないはずです。
import Foundation let first32Char = repeatElement("f", count: 32) let middle32Char = repeatElement("m", count: 32) let last32Char = repeatElement("l", count: 32) let a = (first32Char + ["ab"] + middle32Char + ["ab"] + last32Char).joined() let b = (first32Char + ["bc"] + middle32Char + ["bc"] + last32Char).joined() a == b // false // Foundation a.hash // -4528083392938427260 b.hash // -4528083392938427260 // Swift.Hashable a.hashValue // -8957072229412966235 b.hashValue // -8957072229412966235hashは同じ。hashをファイル変更検知に使ってバグってたことがあった時に調べた。 https://github.com/realm/SwiftLint/issues/1184#issuecomment-274744331enum HogeType: Int { case aaa = 1 case bbb case ccc } ↑ この書き方嫌いなんですけど、意外と賛同してくれる人少ないんだろうかと思ってるんですがどうですか enum HogeType: Int { case aaa = 1 case bbb = 2 case ccc = 3 } IntのrawValueつけるなら全case明示してほしい。Raw value for enum case is not unique というエラーが出たclass A { weak lazy var hoge: B? = nil } class B {} これなんか変なコンパイルエラーなったPlayground execution failed: error: cannot convert return expression of type 'B?' to return type 'B?' error: cannot assign value of type 'B?' to type 'B??' error: cannot assign value of type 'B?' to type 'B??'lazy なくすとエラーなくなるんだけど、 lazy ってその変数の型には影響しないよねweak + lazy ? が参照持てないし使えないのかなと思ったりretain count が増えないのが問題なのかなと思いました ってうまく説明できそうな気がしたが感覚でしかわかってないな。。。cannot assign value of type 'B?' to type 'B??' で、lazyが無いとそのエラーが消えるということは、lazyのあるなしでそのプロパティの型が実は変わっているようなきがするclass A { weak lazy var hoge: B? = B() } class B {} でもこれはこれですぐ解放されるので あまり通って欲しくもない気がするclass A { weak lazy var hoge: B = B() } class B {}
nil になるならまだいいんですけど これだとなおわからない気がするnil になっちゃうんですね class A { lazy var hoge: B! = B() } class B {} let a = A() a.hoge a.hoge = nil a.hoge あー、じゃあ、僕の会話していた時の頭の中が古かった 前まではもう一度初期化されていたはずだから weak + lazy ??? ってなってましたlet a = A() a.hoge // B a.hoge = nil // nil a.hoge // nil Swift3 let a = A() a.hoge // B a.hoge = nil // nil a.hoge // B こういうこと3.1 かどうかは置いておいてこういう時代があったんですよね ResolvedB?? と解釈されてるかどうかが変わっているきがするんだけどどうclass A { weak lazy var hoge: B? = { return B??.none }() } class B {}Playground execution failed: error: cannot convert return expression of type 'B?' to return type 'B?' error: MyPlayground.playground:4:30: error: cannot convert value of type 'B??' to specified type 'B?' weak lazy var hoge: B? = { ^ error: cannot assign value of type 'B?' to type 'B??' error: cannot assign value of type 'B?' to type 'B??'let articlesVC = ArticlesViewController.init { return ArticlesViewModel.init(dataProvider: ArticlesAPIDataProvider.init()) } 本番のコードなんで文脈なくてすまんやけどuninitialized() にすればいけんちゃうみたいなuninitialized() は中身fatalErrorの func uninitialized<T>() -> Tclass VC {} class VM { private weak var _vc: VC? = nil var vc: VC { get { return _vc ?? undefined() } set { _vc = vc } } }class LazyWeak<T> { private weak var _value: T? = nil private func undefined() -> T { fatalError() } var value: T { get { return _value ?? undefined() } set { _value = value } } } class VM { var vc = LazyWeak<VC>() } こういうイメッジclass A { unowned lazy var hoge: B = B() } class B {}Playground execution failed: error: cannot convert return expression of type 'B' to return type 'B' error: MyPlayground.playground:4:32: error: cannot convert value of type 'B' to specified type 'B' unowned lazy var hoge: B = B() ^~~ error: cannot assign value of type 'B' to type 'B?' error: cannot assign value of type 'B' to type 'B?'hoge: B! だとなんか違う怒られするclass A { var block: (() -> ()) = {} func hoge(block: @escaping (() -> ())) { self.block = block block() } } class VC { func viewDidLoad() { let a = A.init() a.hoge { [unowned self] in print(self) } } } VC.init().viewDidLoad()__lldb_expr_98.VC.rx が 生えてるやつでできることを、それ単体だけ Rx 全部を導入しないで採用できないか、ってのがコアアイデアですかね?class DelegateHolder { weak var delegate: SomethingDelegate? } let holder = DelegateHolder() // これは弱参照で持ってほしい。 holder.delegate = SomethingDelegateImpl() // これは強参照で持ってほしい。なぜなら、これを弱参照にすると map の戻り値の参照を誰も保持してないのですぐに回収されてしまうから。 holder.delegate = SomethingDelegateImpl() .map { a in a * 2 } // この差異を吸収するために、weak と strong の両方を持てるインターフェースを持つ必要があった。これを実現しているのが AnyDelegate。GenericError みたいな型を定義する - Error を定義する。言語仕様の方のやつと衝突しちゃうのでそっちを使う時は Swift.Error と完全名で記述する - NSError を使う - protocol DescribedError: Error, CustomStringConvertible { }typealias DescribedError = Error & CustomStringConvertible とかでもいいのかな。enum Error: DescribedErrorって書きたいからextension String : Error {} func a() throws { throw "error message" } do { try a() } catch let e { print(e) // "error message\n" }XCTAssert(max(a, b) == c) | | | | | 7 4 7 | 12 false XCTAssert(a + b > c) | | | | | 4 | 7 | 12 11 false XCTAssert(john.isTeenager) | | | false Person(name: "John", age: 42) XCTAssert(mike.isTeenager && john.age < mike.age) | | | | | | | | | false | | 42 | | 13 | | | | Person(name: "Mike", age: 13) | | | false | | Person(name: "John", age: 42) | false Person(name: "Mike", age: 13)swift-power-assert xctest -Xxcodebuild test -workspace <workspacename> -scheme <schemeName> -sdk iphonesimulator -destination "name=iPhone X,OS=11.2"Chris_Lattner3 とかいう、めっちゃアカウント生成トラブった感じの名前になってるけどwRelease_Notes_for_Xcode_9.3_beta.pdf より ## Known Issues in Xcode 9.3 beta ### Swift Compiler - Conditional conformances are unsupported when performing a dynamic cast (with is or as). これってSwift 4.1リリースでも直らないんだよね? (edited)protocol P { } extension Int: P { } // Fully supported: Set unconditionally conforms to P extension Set: P { } // Not supported in dynamic casts: Array conforms to P // only when its element conforms to P extension Array: P where Element: P { } func castToP(_ value: Any) { if value is P { print("\(type(of: value)) conforms to P"); } else { print("\(type(of: value)) does not conform to P") } } castToP(Set([1, 2, 3])) // unconditional conformances // are supported: // prints "Set<Int> conforms to P castToP([1, 2, 3]) // unsupported conditional conformance: // incorrectly prints "Array<Int> does not // conform to P" castToP([3.141593, 2.71828]) // unsupported conditional conformance: // correctly prints "Array<Double> does not // conform to P" (edited)flatMapのdeprecationはSwift 4.1とSwift 3.3両方だから、4.0.xと3.2.x互換を維持する場合のcompactMap定義は #if (!swift(>=4.1) && swift(>=4.0)) || !swift(>=3.3) extension Array { public func compactMap(_ transform: (Element) throws -> String?) rethrows -> [String] { return try flatMap(transform) } } … みたいに書く必要があるのか。 (edited)#if (!swift(>=4.1) && swift(>=4.0)) || !swift(>=3.3)だった。public protocol Po { func doHoge() } extension Po { public static func getDefaultInstance() -> Po { return DefaultPo() } } internal class DefaultPo: Po { func doHoge() {} } // let po = Po.getDefaultInstance() <- Compile error let po = DefaultPo.getDefaultInstance() なのに今さら気づいた… Protocol は適合する対象であって型としては存在はしないんだなぁというのを実感したfunc hoge(po: Po) // dame func hoge<X: Po>(po: X) // OK なのも実感として納得がいった (edited)assertやpreconditionにクロージャ渡せたらループチェックとかかきやすくて良いんじゃないかと思うんですがどうですかね? もとの定義が@autoclosureなのでそれはずしたのをオーバーロードするだけで行けると思うんですが。assertやpreconditionは最適化によってconditionを評価しないだけで呼出し自体が消えるんじゃないみたいですね。 ずっと勘違いしてました。condition is not evaluated in /// -Ounchecked builds. In -Ounchecked builds, condition is not evaluated, but the optimizer may assume that it always evaluates to true. Failure to satisfy that assumption is a serious programming error.precondition(items.all { $0 >= 0 }) これでいいじゃんlet a = [0, 2, 4, 6] assert({ // all even for e in a { guard e % 2 == 0 else { return false } } return true }())typealias CountableRange がなかったんですが、 4.1 でそれを突っ込むと結構大きめの破壊的変更になる気が。これは 5 で入る PR ですか?typealias でも破壊的か。オーバーロードとか死ぬし。 (edited)typealias O<X> = Optional<X> where X: Sequence O<String>.some("a") O<Int>.some(1) // Error 壊れなくなった可能性があるtypealias O<X> = Optional<X> where X: Sequence O<String>.some("a") //O<Int>.some(1) // Error extension O { func foo() { print("foo") } } Optional<Int>.some(1).foo() //????Swift compiler integration with external tools Potential mentors Rintaro Ishizaki## Swift compiler integration with external tools ## Integration of libSyntax with the rest of the compiler pipeline. ### Potential mentors Rintaro Ishizaki (edited)What are the eligibility requirements for participation? ・You must be at least 18 years of agedo使う場合は変数多くてメソッド分けたくない場合な気がしますねlet hogeObservable と let fugaObservable をこねこね作って、Observable.merge(hogeObservable, fugaObservable) みたいに書きたい時に、 hogeObservable と fugaObservable というローカル変数はなるべくスコープを短くしたいhogeFugaSubscription: do { ... }do 派です。ローカル関数やクロージャ式にすると実行順がコードの記述順と入れ替わる可能性があり、それを意識しないといけないのが難点だと思います。{ ... }() はわかってればいいけど可読性的に微妙かなと。do だと内部から break 等できるけど、ローカル関数やクロージャ式だとできないというのもあります。{ ... }() の方が読みやすい感覚があるんですよね。do{}はパッと見てtryか、と思ってしまうので。do { ... // 開始処理 defer { ... // 終了処理 } guard ... { ... break } ... }do を抜けるタイミングで終了処理を挟み込みたかったんですが、早期脱出もしたかったので、両方の終了処理を共通化しようとしたらこうなったけど、可読性は低いよなぁと。共通化を諦めて個別に書いた方がいい気もしてます。 while ... { do { ... // 開始処理 defer { ... // 終了処理 } guard ... { ... break } ... } ... }do より関数やメソッドに分割が望ましいと思います。
public func AAAAAAA(x: Int) { func step1() { /* ... */ } func step2() { /* ... */ } step1() step2() } public func BBBBBBB(x: Int) { ({ // step 1 /* ... */ })() ({ // step 2 /* ... */ })() } public func CCCCCCC(x: Int) { STEP1: do { /* ... */ } STEP2: do { /* ... */ } }
/* ... */ に十分長い処理を書いて試したところ、-O でも 内部 func と クロージャはインライン化されなかったです。ちょっと意外。LOOP: while ... { ACT1: do { ... // 開始処理 defer { ... // 終了処理 } guard ... { ... break ACT1 } ... } ... } こうかなdo を使うといいながらメソッドに切り出した方がいいというのは変だ・・・。func step1() {の定義は自然に読み飛ばすので、私の目には step1() step2() だけに見える。CCCCCCC が読みやすいですね。do を使いたいという気持ちでした。
let a = ... let b: B do { let t = ... // ちょっと複雑な式 b = foo(t, a) } let c = ...t を foo() の中に書けるけど、可読性のために変数に入れて名前を付けたくて、かといってそれを長々と生かしたくないみたいなケースです。t で済む一時変数にどこで何に使われてるかわかる説明的な名前を付ける必要が出てきませんかt という名前を付けることを意図したわけじゃないですが、僕はそのコンテクストでできるだけシンプルな名前を使うのが好きなので、後続処理と名前がかぶって困るということは結構ある気がします。do なくてもいいんですが、 10-20 行くらいになってくると一度スコープ切っておきたいですね。func これこれこういうイベントで発火するObservableだよ() -> Observable<E> func viewDidLoad() { これこれこういうイベントで発火するObservableだよ() .subscribe { 期待した結果やで } .disposed(by: disposeBag) }func setupこれこれこういうイベントで発火する奴() { viewModel.hoge.subscribe().disposed(by: bag) } こうなってるのがいっぱいある。func これこれこういうイベントで発火するObservableだよ() -> Observable<E> <= これ自体は何回呼んでも、いつ呼んでもいいわけですよね?func outer() { var state1 = ... var state2 = ... func inner1() { } func inner2() {} inner1() inner2() } ↑これ系のスタイルはclass HogeSetUpHelper { var state1 var state2 func inner1() func inner2() func setUp(...) } func outer() { HogeSetUpHelper().setUp(self) }HogeSetUpHelper().setUp(self)viewDidLoad と viewDidUnload の話だ。class X { lazy var setup: Void = { // only 1 time call here }() }_ = setup ?class X { lazy var setup: () -> Void = { print("a") return { } }() } let x = X() x.setup() ほらよ (edited)func nop() { } typealias Setup = () -> Void class X { lazy var setup: Setup = { // 1回だけ return nop }() } 少し見た目をマシにしてみたlet setup = once { } こういう高階関数作れそうじゃない?fooLoop { (`break`: () -> Never) in ... } みたいな break を作りたかったけどできなくて悲しくなった。lazy 内 で self 参照出来るっていうのは正式にOKになったんだっけか。func nop() {} func once(_ f: () -> Void) -> () -> Void { f() return nop } class X { lazy var setup = once { print("1time?") } } let x = X.init() x.setup() x.setup()public func once<T, R>(_ f: @escaping (T) -> R) -> (T) -> R { var done: Bool = false return { (t: T) -> R in guard !done else { fatalError("do not twice") } done = true return f(t) } } (edited)public func once<T, R>(_ f: @escaping (T) -> R) -> (T) -> R { var done: Bool = false return { (t: T) -> R in guard !done else { fatalError("do not twice") } done = true return f(t) } } public class Cat { public init(name: String) { self.name = name self.onBorn() } public var name: String public func onBorn() { _onBorn(self) } private let _onBorn: (Cat) -> Void = once { `self` in print("\(self.name)がうまれた") } } Cat(name: "tama")onBorn を let にしたかったけど self がキャプチャできなかったので func onBorn と let _onBorn に分かれてしまう。public class Cat { public init(name: String) { self.name = name self.onBorn() } public var name: String public lazy var onBorn: () -> Void = once { [unowned self] in print("\(self.name)がうまれた") } }once動かないのでは。public func once<T, R>(_ f: @escaping (T) -> R) -> (T) -> R { var done: Bool = false return { (t: T) -> R in guard !done else { fatalError("do not twice") } done = true return f(t) } } class Cat { let born = once { () in print("mew") } } let c = Cat() c.born(()) c.born(())public class Cat { public init(name: String) { self.name = name self.onBorn() } public var name: String public lazy var onBorn: () -> Void = once { [unowned self] in print("\(self.name)がうまれた") } }[weak self] _ in guard let `self` = self else { return } これで (edited)deinitちゃんと呼ばれるのね。 func once(_ f: () -> Void) -> () -> Void { f() return {} } public class Cat { public init(name: String) { self.name = name self.onBorn self.onBorn } public var name: String public lazy var onBorn = once { print("\(self.name)がうまれた") } deinit { print("deinit") } } do { Cat(name: "test") }onceがVoidではなく() -> Voidを返すのも地味に良い。Voidだとlazyの受け側に型指定がないとwarningが出るので。lazyでself参照出来るようになったのはSwift 4.0から?public struct S { init() {} public lazy var p = self.f() func f() -> String { return "f()" } } var s = S() s.p が error: use of unresolved identifier 'self' public lazy var p = self.f() ^~~~ になります。 (edited)swift-4.0-DEVELOPMENT-SNAPSHOT-2017-06-06-a以降ですね。if caseパターンって、キャスト?もされるのね。知らなかった。 import Foundation enum MyErrorEnum: Error { case message(String) } struct MyErrorStruct: Error {} class MyErrorClass: Error {} extension String: Error {} func check(error: Error) { if case MyErrorEnum.message = error { print("expected error: \(error)") } else { print("unexpected error: \(error)") } } check(error: MyErrorEnum.message("error")) check(error: NSError(domain: "custom error", code: -1, userInfo: nil)) check(error: MyErrorStruct()) check(error: MyErrorClass()) check(error: "StringError")
expected error: message("error") unexpected error: Error Domain=custom error Code=-1 "(null)" unexpected error: MyErrorStruct() unexpected error: __lldb_expr_90.MyErrorClass unexpected error: StringError (edited)XCTAssertThrowsError(try YAMLDecoder().decode(Sample.self, from: invalidYaml)) { error in if case DecodingError.typeMismatch(_, _) = error {} else { XCTFail("unexpected error: \(error)") } } の様に記述できる。 (edited)switch x { case 0: break case 1: print(y) print(z) default: print(y) print(z) } こういう複数のcaseを1行に書いたら構文エラーをレポートする。コンパイルはswiftcだからビルドはできる。独自Parserがあるんだな。Consecutive statements on a line must be separated by ';' になっちゃうと思いますが。case 1 の時に print(y);print(z) の動作ですか?case 1 見落としやすいので構文エラーにして欲しい感 is ある func foo() {} func bar() {} これも曖昧ではないけどエラーになるので、同じポリシーで行くべきだと思います。class A{}; protocol B {};とかはセミコロン必要ですよね。if value==1 {}はOKだけどif velue!=1 {}これがダメなのは理解できるけどわかりにくいから演算子は全部スペース必要でいいんじゃないかと思ったりしてます。0..<(n*2) (edited)...や..<と変わるのが微妙そうですね0 ..< 3 と..<3で違うスペースの入れ方が強制されるのは微妙だなと..<3 は許されるのに 1..<3 が許されないのは揃ってないということか..< 3が許されてないのはいいんかという話にもなりかねませんがprotocol A { associatedtype B associatedtype C where C == B.Hoge } struct D: A { typealias B = String typealias C = String }
where C == B.Hoge のHogeという型がBに無いのにコンパイルが通ってしまった。where句の制約は無視されるようになってしまいましたprotocol HasHoge { associatedtype Hoge } protocol A { associatedtype B: HasHoge associatedtype C where C == B.Hoge } struct D: A { typealias B = String typealias C = String } 健全な形はこうか。B.Hoge って書いてある時点でエラーになりそうなのに確かに通るねSomeType: SomeProtocol みたいなジェネリクスはもちろん必要だけど、逆に SomeType: !SomeProtocol みたいなジェネリクスも地味に欲しいよな…<T: FooEnum> where T != case .foo> みたいなこともしたい・・・。case の一部を禁じたいこと多い。enum じゃなくて sealed class で) (edited)public class Holder<T> {} extension Holder { public func ho() { print("ho1") } } extension Holder where T == String { @available(*, unavailable) public func ho() { print("ho2") } } let a = Holder<Int>() a.ho() // これでいけるかと思ったら ho1 が出力された・・・ let b = Holder<String>() b.ho() 作戦失敗 (edited)enum NetworkError: Error { case timedOut case cannotFindHost case notConnectedToInternet } enum MyAPIError: NetworkError { case responseInvalid case sessionExpired case notEnoughMinerals case insufficientVespineGas } (edited)case を追加できちゃわない?: NetworkError だけど、 NetworkError として扱えるわけではない?? (edited)enum Foo: Int は Int に入れられるわけじゃないからいいのかな?: Foo に新たな概念を追加することになるのか・・・。enum MyAPIError { spread case NetworkError case responseInvalid case sessionExpired case notEnoughMinerals case insufficientVespineGas } ↑こんな記法だったら良さそう。 (edited)T: !Optional ですねwT: !Optional
fun <T: Any> foo() (edited)// 親?クラス struct Animal { var name: String func speak() -> String { return "I am \(name)" } } // トリックここから protocol AnimalExtend { var animal: Animal { get set } var name: String { get set } func speak() -> String } extension AnimalExtend { var name: String { get { return animal.name } set { animal.name = newValue } } func speak() -> String { return animal.speak() } } // トリックここまで // ユーザー例 // プロトコル指定は継承指示 struct Cat : AnimalExtend { // コンパイルエラーがでるのでこれを定義 var animal: Animal // 必然的にこれも書くことになる init(name: String) { animal = Animal(name: name) } } print(Cat(name: "tama").speak()) // okAny? がトップタイプですからねぇ。 Any で縛れば nullable を弾けますが、 Swift の Optional は union じゃないから同じことはできないんですよねぇ。Optional<Optional<T>> ができるのは魅力的ですがOptional のネストはほしいですね。つい最近もやっぱいるよなと思ったけど何だったかな・・・。struct の継承もほしい。struct Path: String { // パス操作のための便利メソッド }Path を型として分離できるし、 String として使いたいときはそのまま代入できる。transparent struct Path: String { } みたいな。 (edited)Path is String であるためには。let s: String = path ができたい。func asString() -> String が 自動で is や as で呼び出されれば大丈夫String is Path も取りたいなら駄目ですけどねString is Path だと意味がない。Path のところに String 渡せてしまうから。.asString() で。Path はあくまで String なんだけど、 Path として扱っているときは String を突っ込まれたくない。String に Path は入れたいけど Path に String は入れたくない。typealias Path = String だと Path に String を突っ込めてしまうけどString を引数にとる関数に Path を渡すときにいちいち変換したくない。String と Path で話してるからわかりづらいのかも。struct Age: Int {}Weight: Int と Height: Int から BMI 計算するときにprotocol IntConvertible { func asInt() -> Int } extension Age : IntConvertible {} こうしておいて、X: IntConvertibleで受ければFloat と Double はメモリレイアウトが違うし別の型だけどAge は Int の用途を絞りたいだけだから、Age is Int は OK だと思うんよね。Float とかにするわけでしょ?struct Weight { let value: Float } とか作って区別するっていうならわかるけど。typealias TimeInterval = Double じゃない?独自に作ったってこと?Float にアップキャストされない方がいいような気もしてきた。1999年、NASAの火星探査衛星マーズ・クライメート・オービターは、制御プログラムの力の単位にポンド重とニュートンが混在していたために、計画よりはるかに低い軌道に投入されてしまい、火星大気との摩擦により墜落してして失われてしまいました。単位計算のルールを型システムにエンコードできれば、コンパイル時にすべての単位エラーを検出できるはずです。enum と同じように、 struct Path: String したら、 path.rawValue で String が得られるとかでいいのかも?わざわざ構文増やさなくても、↓書けばいいだけかな・・・。 struct Path { let rawValue: String }public init の実装必須のはず。 (edited): String の意味はあるか?dispatch_once で検索すると出てくる let myGlobal = { … global contains initialization in a call to a closure … }() _ = myGlobal // using myGlobal will invoke the initialization code only the first time it is used.JSONEncoderとJSONDecoder互換のクラスを追加してみた。 https://github.com/norio-nomura/ObjectEncoder/pull/18JSONSerializationへ渡す/から受け取るobjectをエンコード/デコードしてる。classの場合 のコードがうごくのはおかしいよねっとw https://qiita.com/noppefoxwolf/items/a9d2a103d54b2b1ea415class でも self を書き換え可能な mutating func がほしいなぁと感じてます。static func で違う Self 返すしかないですねFoo に対して func update(foo: Foo, ...) -> Foo { ... } と class Foo { func update(...) -> Foo { ... } } があって、 (edited)var foo = ... foo = update(foo: foo, ...) foo = foo.update(...) と書くのをclass User: Initializable { var id: Int = 1000 /* 暗黙の */ init() {} } extension Initializable { init() { self = Factory.make(type: Self.self) } } User() で、暗黙の User.init() に直接ディスパッチされていると思います。 (edited)func update(foo: inout Foo, ...) { ... } のように inout にして update(foo: &foo, ...) はできるけど、 mutating func がないので対応するメソッド版 update を作れないです。mutating func は self を inout に持つ関数という文脈で)Account の id の初期値をなくすと、それもそのままコンパイルできちゃってStackOverflowになりますinit(id: Int) になるので Initializable.init() と Factory.make(type:) で無限再帰ですね。@tarunon さん、 @rintaro さんと @omochimetaru さんと議論して パワーワードだwfunc bar() { foo() } func foo() { bar() } (edited)@_transparent つけると、先に展開されてからの検知になるので、警告してくれましたが。func generate() -> UInt32 { let a = arc4random_uniform(10) if a > 10 { return a } else { return generate() } }func generate() -> UInt32 { let a = arc4random() % 10 if a > 10 { return a } else { return generate() } }$ swift Welcome to Apple Swift version 4.1 (swiftlang-902.0.43 clang-902.0.37.1). Type :help for assistance. 1> Optional(1).map(dump) error: repl.swift:1:17: error: ambiguous reference to member 'dump(_:to:name:indent:maxDepth:maxItems:)' Optional(1).map(dump) ^~~~ (edited) 1> :type lookup dump @discardableResult @_inlineable @_semantics("optimize.sil.specialize.generic.never") func dump<T>(_ value: T, name: Swift.String? = default, indent: Swift.Int = default, maxDepth: Swift.Int = default, maxItems: Swift.Int = default) -> T @discardableResult @_inlineable @_semantics("optimize.sil.specialize.generic.never") func dump<T, TargetStream>(_ value: T, to target: inout TargetStream, name: Swift.String? = default, indent: Swift.Int = default, maxDepth: Swift.Int = default, maxItems: Swift.Int = default) -> T where TargetStream : TextOutputStream#lineとか使っててマクロがないSwiftでは詰むfunc dump<T>(name: String?=nil, indent: Int=0, maxDepth: Int=0, maxItems: Int=0) -> (T) -> Void { return { value in dump(value, name: name, indent: indent, maxDepth: maxDepth, maxItems: maxItems) } } (Int?.none).map(dump())f(a, b, c, d) に対して 好きな引数を埋めた関数を得る操作があると便利か?extension Array { func mapSpecialized<U>(_ type: U.Type=U.self) -> ((Element) -> U) -> [U] { return { self.map($0) } } } こういうの作るとmapを取り回せるようになるvar a = [2, 3, 5] var b = a a.withUnsafeMutableBufferPointer { $0.baseAddress!.pointee = -1 } print(a) // [-1, 3, 5] print(b) // [2, 3, 5]
var a = [2, 3, 5] var b = a a.withUnsafeBufferPointer { UnsafeMutablePointer(mutating: $0.baseAddress!).pointee = -1 } print(a) // [-1, 3, 5] print(b) // [-1, 3, 5]withUnsafeMutable~~は実行した瞬間コピーされてるんですかね? 中身で書き換えるかどうかまで判断してたら相当賢そうですけどwithUnsafeBufferPointer 使えばいいわけだし問題はなさそう。UnsafeMutablePointer の pointee に参照型のインスタンス set するとリファレンスカウント増える??増えないと思ってた。 extension Array { mutating func update(_ body: (inout Element) throws -> ()) rethrows { let count = self.count try withUnsafeMutableBufferPointer { var pointer = $0.baseAddress! for _ in 0..<count { try body(&pointer.pointee) pointer += 1 } } } } class Cat { let name: String init(_ name: String) { self.name = name } deinit { print("deinit: \(name)") } } var a = [Cat("a"), Cat("b"), Cat("c")] a.update { $0 = Cat("\($0.name)2") }
deinit: a deinit: b deinit: cUnsafeRawPointer としてコピーとかすると壊れるのか。update は問題なさそうだけど、これより速い実装ってあるかな?count が無駄かと思ってポインタを比較してループ回してたけどDispatchQueue.concurrentPerformを使ったconcurrentUpdateとか。extension Array { mutating func update(_ body: (inout Element) throws -> ()) rethrows { let count = self.count try withUnsafeMutableBufferPointer { var pointer = $0.baseAddress! let end = pointer + count while pointer != end { try body(&pointer.pointee) pointer += 1 } } } }getBase() ..< getBase() + count を getBase() 一回で綺麗に書く構文って現状ありましたっけ? for pointer in $0.baseAddress! ..< $0.baseAddress! + count { try body(&pointer.pointee) } をもっと短く書きたい。string[string.index(string.startIndex, offsetBy: 3) ..< string.index(string.startIndex, offestBy: 6)] これも短く書きたい (edited)string[offset: 3..<6] の議論はどんな感じなんだっけな。$0.baseAddress! ..< $0.baseAddress! + count できるの知らなかったーinfix operator ~> : StridePrecedence prefix operator ~> infix operator ~>- : StridePrecedence prefix operator ~>- infix operator ...~> infix operator ...~>-public func ~>-(range: CountableRange<Int>, stride: Int) -> NDArrayIndexElement { return range ~> (-stride) }a~>-b は a ~> (-b) なのねoperator の上書きが出来ることを初めて知った。 ~> は stdlib で既に定義されているので、:soon: 入れると勝手に brew tap el-hoshino/zundoko brew install zundoko そして使い方は zundoko の後に適当に何か英文章書きます、何が出力されるかはEnter押してからのお楽しみw zundoko try! Swift is Good! a...swiftc --emit-silと書いてしまうjava -version さんパターンだ--version になるよみたいな話を観た気がしてウキウキして java 9 いれて --version してそんなオプションネーヨと言われた気持ち
1do try 文だとネストが深くなるから、guard try let error {as XxxError} 文欲しくなった今日の今頃guard try? else と同じような挙動で、guard と同じ階層で正常系を描く処理ですね、ただ guard try? は error を消すけどこちらは消さないguard let player = try AVAudioPlayer(name: name) catch let error as NSError { print(error) // エラーハンドリング return } catch let error { return } player.play() みたいな (edited)do { try ... } catch { print(error) // エラーハンドリング return }do の中で書くとネストが深くなるのがちょっと微妙に嫌ですねguard let Type = Type? も guard let Type = try Type も同じようなものだと思うんですよね、どちらも「確実な Type が欲しい」というわけで-plistArg '{"foo" = bar; "array" = ("foo", {"bar" = "baz"; } ); }' と -xmlArg "<dict><key>foo</key><string>bar </string><key>baz</key><string>qux</string></dict>" をフォーマットを事前に指定することもなく、両方使えるようにするとか普通に考えておかしいなあと。protocol HasCodingKeys: Codable {} extension HasCodingKeys { func encode(to encoder: Encoder) throws { fatalError() } init(from decoder: Decoder) throws { fatalError() } } struct A: HasCodingKeys { private typealias Keys = CodingKeys // Use of undeclared type 'CodingKeys' }
Codable の init(from decoder: Decoder) とfunc encode(to encoder: Encoder) をprotocol extensionに実装すると、Aの中でCodingKeys がundeclaredになるんですが、どういう仕組みになってるんですかね。 (edited)struct A: HasCodingKeys { typealias Keys = CodingKey }struct A: Codable { struct B {} let b: B typealias Keys = CodingKeys } これを通したかったみたいでした。 (edited)@available(*, unavailable)って出来ない?setterだけじゃなくgetterの場合もなんですよね。 以前subscriptのsetterだけ定義したくて試してだめだったのでvar _x: Int = 0 var x: Int { @available(*, unavailable) get { return _x } @available(*, unavailable) set { _x = newValue } } print(x) // 0 x = 100 print(_x) // 100 (edited)@availableだけの話では無いですよね。private(get)も無いから。subscriptやプロパティである必要がない、ってことなのではないかと思います。 (edited)private var privateValue = 0 func setValue(_ value: Int) { privateValue = value }deprecated は実装されそう。 (edited)foo.bar.baz = 1 で、foo の getter の方が絞られていると bar がそもそも取り出せないので、変な感じになってくるとかはありそうですね。
(edited)setHogehoge(~)があってgetHogehoge()がないのはそこまで違和感を覚えないimport XCTest @testable import pow let lhs = 10 let rhs = 10 let count = 1000000 let expect = Int(pow(Double(lhs), Double(rhs))) final class powTests: XCTestCase { func test0() { var x: Int = 0 measure { for _ in 0..<count { x = power0(lhs, rhs) } } XCTAssertEqual(x, expect) } …expectの算出に使ってるInt(pow(Double(lhs), Double(rhs)))の速度も測ろうと考え func test_() { var x: Int = 0 measure { for _ in 0..<count { x = Int(pow(Double(lhs), Double(rhs))) } } XCTAssertEqual(x, expect) } を追加したら、10000倍くらい速かった。x = expectに書き換えてただけだった…pow が参照等価であることをどうやって知ってるんですか?let expect = Int(pow(Double(lhs), Double(rhs)))ってのがあって、テストtest_()内でそのexpectを参照してるのと、Int(pow(Double(lhs), Double(rhs)を別モジュールの関数にした場合と速度差がありすぎることから、x = expectにしているという僕の推測です。 (edited)test_()内のループカウンタをどれだけ増やしても実行時間が変わらないので、ループ自体が無くなってるのかも?@inline(never) public func blackHole<T>(_ x: T) {} に食わせて、最適化を防いでますね。 measure { for _ in 0..<count { blackHole(Int(pow(Double(lhs), Double(rhs)))) } }x = expect になってるんだったら blackHole(expect) になるだけだから防げないか。 (edited)echo 'import Foundation; let lhs = 10, rhs = 9, count = 10000000, expect = Int(pow(Double(lhs), Double(rhs))); func test() { var x: Int = 0; for _ in 0..<count { x = Int(pow(Double(lhs), Double(rhs))) }; print(x == expect) }; test()'|swiftc -emit-assembly - -O|xcrun swift-demangle (edited)powの呼び出し自体がなくなってるぽい。-Ononeにするとcallq _powが2箇所現れる。x = expectにしてるわけでは無く、コンパイル時に定数になってるぽい。 movq $10, _main.lhs : Swift.Int(%rip) movq $9, _main.rhs : Swift.Int(%rip) movq $10000000, _main.count : Swift.Int(%rip) movq $1000000000, _main.expect : Swift.Int(%rip) callq _main.test() -> () (edited)powの呼び出しが残ってる。@llvm.pow.f64 に置き変えですか? (edited)-emit-irでpowは無くなって定数1000000000になってますね。 define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 { entry: store i64 10, i64* getelementptr inbounds (%TSi, %TSi* @main.lhs : Swift.Int, i64 0, i32 0), align 8 store i64 9, i64* getelementptr inbounds (%TSi, %TSi* @main.rhs : Swift.Int, i64 0, i32 0), align 8 store i64 10000000, i64* getelementptr inbounds (%TSi, %TSi* @main.count : Swift.Int, i64 0, i32 0), align 8 store i64 1000000000, i64* getelementptr inbounds (%TSi, %TSi* @main.expect : Swift.Int, i64 0, i32 0), align 8 tail call swiftcc void @main.test() -> ()() ret i32 0 }emit-ir はLLVM最適化後でした。 https://twitter.com/rintaro/status/963754184494350336-disable-llvm-optzns をフロントエンドに渡してあげると見えるかもしれない。$ echo 'import Foundation; let lhs = 10, rhs = 9, count = 10000000, expect = Int(pow(Double(lhs), Double(rhs))); func test() { var x: Int = 0; for _ in 0..<count { x = Int(pow(Double(lhs), Double(rhs))) }; print(x == expect) }; test()'|swiftc -frontend -emit-ir -primary-file - -target x86_64-apple-darwin17.4.0 -enable-objc-interop -sdk /Applications/Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.13.sdk -O -color-diagnostics -disable-llvm-optzns -module-name main -o - |xcrun swift-demangle$ echo 'import Foundation; let lhs = 10, rhs = 9, count = 10000000, expect = Int(pow(Double(lhs), Double(rhs))); func test() { var x: Int = 0; for _ in 0..<count { x = Int(pow(Double(lhs), Double(rhs))) }; print(x == expect) }; test()' | swiftc -O -emit-ir -Xfrontend -disable-llvm-optzns -define i32 @main(i32, i8**) #0 { entry: %2 = bitcast i8** %1 to i8* store i64 10, i64* getelementptr inbounds (%TSi, %TSi* @main.lhs : Swift.Int, i32 0, i32 0), align 8 store i64 9, i64* getelementptr inbounds (%TSi, %TSi* @main.rhs : Swift.Int, i32 0, i32 0), align 8 store i64 10000000, i64* getelementptr inbounds (%TSi, %TSi* @main.count : Swift.Int, i32 0, i32 0), align 8 %3 = call double @pow(double 1.000000e+01, double 9.000000e+00)
pow残ってる。define i32 @main(i32, i8**) #0 { entry: %2 = bitcast i8** %1 to i8* store i64 10, i64* getelementptr inbounds (%TSi, %TSi* @_T04main3lhsSivp, i32 0, i32 0), align 8 store i64 9, i64* getelementptr inbounds (%TSi, %TSi* @_T04main3rhsSivp, i32 0, i32 0), align 8 store i64 10000000, i64* getelementptr inbounds (%TSi, %TSi* @_T04main5countSivp, i32 0, i32 0), align 8 %3 = call double @pow(double 1.000000e+01, double 9.000000e+00) %4 = bitcast double %3 to i64 ... declare double @pow(double, double) #1 この時点ではまだ 普通のpowですね。powは単純なforループ版より3~9倍遅かった。x = expect にしているという僕の推測です。 pow が参照等価であることをコンパイラが知らないと x = expect とすることができないんじゃないかと思ったんですが、そもそもコンパイル時に展開されているということは pow が特別扱いされてそうですね。
/// canConstantFoldCallTo - Return true if its even possible to fold a call to /// the specified function. bool canConstantFoldCallTo(ImmutableCallSite CS, const Function *F);canConstantFoldCallToの実装。 https://github.com/apple/swift-llvm/blob/stable/lib/Analysis/ConstantFolding.cpp#L1441switch のパターンマッチに ? 使えるの知らなかったif case let だけかと思ってた。 let a: Int? = 42 switch a { case let x?: print(x + 1) // 43 default: print("nil") }.some(let x) って書いてた。.some(let x) にしてた。x?. の時は ?. だけど x?: の時は x? : なのが紛らわしいな。: は演算子には使えない文字なんだっけ。switch (open, close) { case (let open?, let close?): return "\(open)〜\(close)" case (let open?, nil): return "\(open)〜" case (nil, let close?): return "〜\(close)" case (nil, nil): return "" } 最近こんなん書いたけど、?ついてるからややこしいなーと (edited).some の方が可読性高い?? ついてると一瞬脳が Optional と認識してしまいそうかも?if case let a? = aOrNil はうまい表現だと思うんだよなぁ。宣言しているのはあくまで a で ? が剥がされてる感が。if let a? = aOrNil にしてほしい。else ifでかかなきゃならない?if case の1行表記が欲しいenum Animal { case cat(Cat) case dog ... } ↑で animal: Animal から Cat? を取り出したい (edited)run { if case .cat(let x) = animal { return x } else { return nil } } (edited)Cat? を取り出しても、大抵のケースでは結局その後で分岐することになるのでは?button.isEnabled = ... みたいなときに Bool がほしいのはある気がする。Observable<Animal> から Observable<Cat>` に変換する時とかにほしいんですよArray<Animal> から Array<Cat> に compactMap するとかでもいいですね。switch か if case して return するしかなさそうだなぁ。 (edited)'public' modifier cannot be used with extensions that declare protocol conformances と言われるんですが、なぜそうなってるんでしょう?(でも外からはちゃんと認識されてるっぽい)extension Polynomial: EuclideanRing where R: Field {protocol Collection: Sequence みたいに書くのとはまた違う感じでしょうか?func bar(foo: int) { func inner(arg: int = foo) {} print(inner()) } bar(foo: 3)Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnu/usercode/main.swift:1:15: error: use of undeclared type 'int' func bar(foo: int) { ^~~ /usercode/main.swift:2:21: error: use of undeclared type 'int' func inner(arg: int = foo) {} ^~~func bar(foo: Int) { func inner(arg: Int = foo) {} print(inner()) } bar(foo: 3)Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnuswift: /home/buildnode/jenkins/workspace/oss-swift-4.1-package-linux-ubuntu-16_04/swift/lib/SILGen/SILGenGlobalVariable.cpp:64: bool isGlobalLazilyInitialized(swift::VarDecl *): Assertion `!var->getDeclContext()->isLocalContext() && "not a global variable!"' failed. /usr/bin/swift[0x3f24d54] /usr/bin/swift[0x3f25096] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f15d2b98390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f15d12d7428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f15d12d902a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f15d12cfbd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f15d12cfc82] /usr/bin/swift[0xc929db] /usr/bin/swift[0xc6a1e3] /usr/bin/swift[0xc6af00] /usr/bin/swift[0xc7448c] /usr/bin/swift[0xc69ee4] /usr/bin/swift[0xcc47f6] /usr/bin/swift[0xc91f8d] /usr/bin/swift[0xc2e86b] /usr/bin/swift[0xc2c51b] /usr/bin/swift[0xc2b847] /usr/bin/swift[0xcc1225] /usr/bin/swift[0xcc106e] /usr/bin/swift[0xc8fec5] /usr/bin/swift[0xc33515] /usr/bin/swift[0xc2ba85] /usr/bin/swift[0xc30f7b] /usr/bin/swift[0xc31c46] /usr/bin/swift[0xc3221d] /usr/bin/swift[0x4c27c4] /usr/bin/swift[0x4beecc] /usr/bin/swift[0x4778c4] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f15d12c2830] /usr/bin/swift[0x475179] Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -module-name main 1. While emitting SIL for 'bar(foo:)' at /usercode/main.swift:1:1 2. While silgen emitFunction SIL function "@_T04main3barySi3foo_tF". for 'bar(foo:)' at /usercode/main.swift:1:1 3. While silgen emitDefaultArgGenerator SIL function "@_T04main3barySi3foo_tF5innerL_ySi3arg_tFfA_". for expression at [/usercode/main.swift:2:27 - line:2:27] RangeText="f" Aborted (core dumped)Assertion !var->getDeclContext()->isLocalContext() && "not a global variable!"' failed. (edited)struct Stone {} extension Stone { func aaa<T>(_ t: T) {} }protocol A {} protocol B {} protocol C {} extension A: B where Self: C {} extension B: C where Self: A {} extension C: A where Self: B {}2018-03-31-a 4.1 4.0.3 3.1.1 3.0.2func bar(foo: Int) { func inner(arg: Int = foo) {} print(inner()) } bar(foo: 3)Swift version 4.1 (swift-4.1-RELEASE) Target: x86_64-unknown-linux-gnuswift: /home/buildnode/jenkins/workspace/oss-swift-4.1-package-linux-ubuntu-16_04/swift/lib/SILGen/SILGenGlobalVariable.cpp:64: bool isGlobalLazilyInitialized(swift::VarDecl *): Assertion `!var->getDeclContext()->isLocalContext() && "not a global variable!"' failed. /usr/bin/swift[0x3f24d54] /usr/bin/swift[0x3f25096] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f6befe6f390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f6bee5ae428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f6bee5b002a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f6bee5a6bd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f6bee5a6c82] /usr/bin/swift[0xc929db] /usr/bin/swift[0xc6a1e3] /usr/bin/swift[0xc6af00] /usr/bin/swift[0xc7448c] /usr/bin/swift[0xc69ee4] /usr/bin/swift[0xcc47f6] /usr/bin/swift[0xc91f8d] /usr/bin/swift[0xc2e86b] /usr/bin/swift[0xc2c51b] /usr/bin/swift[0xc2b847] /usr/bin/swift[0xcc1225] /usr/bin/swift[0xcc106e] /usr/bin/swift[0xc8fec5] /usr/bin/swift[0xc33515] /usr/bin/swift[0xc2ba85] /usr/bin/swift[0xc30f7b] /usr/bin/swift[0xc31c46] /usr/bin/swift[0xc3221d] /usr/bin/swift[0x4c27c4] /usr/bin/swift[0x4beecc] /usr/bin/swift[0x4778c4] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f6bee599830] /usr/bin/swift[0x475179] Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -module-name main 1. While emitting SIL for 'bar(foo:)' at /usercode/main.swift:1:1 2. While silgen emitFunction SIL function "@_T04main3barySi3foo_tF". for 'bar(foo:)' at /usercode/main.swift:1:1 3. While silgen emitDefaultArgGenerator SIL function "@_T04main3barySi3foo_tF5innerL_ySi3arg_tFfA_". for expression at [/usercode/main.swift:2:27 - line:2:27] RangeText="f" Aborted (core dumped)func bar(foo: Int) { func inner(arg: Int = foo) {} print(inner()) } bar(foo: 3)Swift version 4.2-dev (LLVM 0d52728a8a, Clang 1d3cad1e6b, Swift 6c42bcccbd) Target: x86_64-unknown-linux-gnuswift: /home/buildnode/jenkins/workspace/oss-swift-package-linux-ubuntu-16_04/swift/lib/SILGen/SILGenGlobalVariable.cpp:64: bool isGlobalLazilyInitialized(swift::VarDecl *): Assertion `!var->getDeclContext()->isLocalContext() && "not a global variable!"' failed. /usr/bin/swift[0x411c854] /usr/bin/swift[0x411cb96] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f64a8588390] /lib/x86_64-linux-gnu/libc.so.6(gsignal+0x38)[0x7f64a6cc7428] /lib/x86_64-linux-gnu/libc.so.6(abort+0x16a)[0x7f64a6cc902a] /lib/x86_64-linux-gnu/libc.so.6(+0x2dbd7)[0x7f64a6cbfbd7] /lib/x86_64-linux-gnu/libc.so.6(+0x2dc82)[0x7f64a6cbfc82] /usr/bin/swift[0xcb8bb3] /usr/bin/swift[0xc8d123] /usr/bin/swift[0xc8dde3] /usr/bin/swift[0xc9e360] /usr/bin/swift[0xc8cef4] /usr/bin/swift[0xcecb34] /usr/bin/swift[0xcb8091] /usr/bin/swift[0xc4fb59] /usr/bin/swift[0xc4d64f] /usr/bin/swift[0xc4c878] /usr/bin/swift[0xce96b5] /usr/bin/swift[0xce94fe] /usr/bin/swift[0xcb5f5b] /usr/bin/swift[0xc54c84] /usr/bin/swift[0xc4cb25] /usr/bin/swift[0xc525bb] /usr/bin/swift[0xc53266] /usr/bin/swift[0xc5385d] /usr/bin/swift[0x4d820d] /usr/bin/swift[0x4d4b9c] /usr/bin/swift[0x48a26d] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7f64a6cb2830] /usr/bin/swift[0x487ac9] Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret /usercode/main.swift -disable-objc-interop -module-name main 1. While emitting SIL for 'bar(foo:)' at /usercode/main.swift:1:1 2. While silgen emitFunction SIL function "@$S4main3bar3fooySi_tF". for 'bar(foo:)' at /usercode/main.swift:1:1 3. While silgen emitDefaultArgGenerator SIL function "@$S4main3bar3fooySi_tF5innerL_3argySi_tFfA_". for expression at [/usercode/main.swift:2:27 - line:2:27] RangeText="f" Aborted (core dumped)func foo<T>(_ array: [T?]) -> [T] { ... } はできるのに↓ができないのは、関数よりもメソッドを優先する Swift としては明らかな言語仕様的不足。 extension<T> Array where Wrapped == T? { func foo() -> [T] { ... } }OptionalProtocol 、昔は where T == Int? とかでも必要だったけどこれは解消してマシになったんですけど、まだ == T? が書けないんですよねぇ。compactMap の Proposal に書かれてる compact も実装できない・・・。 https://github.com/apple/swift-evolution/blob/master/proposals/0187-introduce-filtermap.mdextension<T> Array where Element == T? { func foo() -> [T] { ... } } (edited)extension Array where Element: OptionalConvertible { ... } extension Optional : OptionalConvertble { ... } (edited)public protocol OptionalConvertible { associatedtype _Wrapped func asOptional() -> Optional<_Wrapped> } extension Optional : OptionalConvertible { public func asOptional() -> Optional<Wrapped> { return self } }public protocol EquivalenceRelation { .. } public struct QuotientSet<X, Rel: EquivalenceRelation>: SetType where X == Rel.Base { .. } public struct ModSubgroupRelation<H: Subgroup>: EquivalenceRelation { .. } public typealias QuotientGroup<G, H: Subgroup> = QuotientSet<G, ModSubgroupRelation<H>> where G == H.Super extension QuotientGroup: Group where X: Group, Rel: ModSubgroupRelation<H> // あっprotocol A {} struct X<T: A> {} struct B<S>: A{} typealias Y<S> = X<B<S>> extension<S> Y where T == B<S> { .. } // コレ (edited)protocol A {} struct X<T: A> {} struct B<S>: A{} typealias Y<S> = X<B<S>> protocol BProtocol: A { associatedtype _S var bValue: B<_S> { get } } extension B : BProtocol { var bValue: B<S> { return self } } extension X where T : BProtocol { // これがやりたい }extension<S> Y where T == B<S> は extension<S> X where T == B<S> と同じ意味になると思います。Optional の話と合わせると BProtocol を BConvertible とした方がよかったかもしれません。BProtocl は B に変換できるので実質的に B のように扱えます。public protocol _ModSubgroupRelation: EquivalenceRelation where Base == Sub.Super { associatedtype Sub: Subgroup } public struct ModSubgroupRelation<H: Subgroup>: _ModSubgroupRelation { public typealias Base = H.Super public typealias Sub = H ... } public typealias QuotientGroup<G, H: Subgroup> = QuotientSet<G, ModSubgroupRelation<H>> where G == H.Super extension QuotientGroup: Group where Rel: _ModSubgroupRelation, X == Rel.Base { ... } できたっぽいです!_ModSubgroupRelation プロトコルから ModSubgroupRelation を取り出すメソッドかプロパティをつけないといけないと思います。 (edited)protocol P{} struct A<T> {} extension A: P where T == Int {} extension A: P where T == String {} // error: redundant conformance of 'A<T>' to protocol 'P' 異なる条件でも同じ protocol への conformance はできないんですね…protocol IntOrString {} extension Int: IntOrString {} extension String: IntOrString {} extension A: P where T: IntOrString {} みたいに回り道が必要になりますねぇprotocol A {} protocol B: A {} protocol C: A {} protocol D: B, C {} struct X<T>: A{} extension X: D where T == Int { // Type 'X<T>' does not conform to protocol 'B' }Swift version 4.1 (swift-4.1-RELEASE)/usercode/main.swift:7:1: error: type 'X<T>' does not conform to protocol 'B' extension X: D where T == Int { // Type 'X<T>' does not conform to protocol 'B' ^ /usercode/main.swift:4:10: note: type 'X<T>' does not conform to inherited protocol 'B' protocol D: B, C {} ^protocol A {} protocol B: A {} protocol C: A {} protocol D: B, C {} struct X<T>: A{} extension X: B where T == Int {} extension X: C where T == Int {} extension X: D where T == Int {}Swift version 4.1 (swift-4.1-RELEASE)protocol A {} protocol B: A {} protocol C: A {} protocol D: B, C {} struct X<T>: A{} extension X: B, C, D where T == Int {}Swift version 4.1 (swift-4.1-RELEASE)extension BilinearMap: VectorSpace, BilinearMapType where Domain: ProductSetType & VectorSpace, Domain.Left: VectorSpace, Domain.Right: VectorSpace, Codomain: VectorSpace, Domain.CoeffRing == Codomain.CoeffRing, Domain.CoeffRing == Domain.Left.CoeffRing, Domain.CoeffRing == Domain.Right.CoeffRing {extension <V1: VectorSpace, V2: VectorSpace, W: VectorSpace> BilinearMap: BilinearMapType where Domain == ProductVectorSpace<V1, V2>, Domain.CoeffRing == Codomain.CoeffRing { } これで済むと思います。extension<T> Array where Element == Optional<T> { func compact() -> Array<T> { ... } } の代わりに func compact<T>(_ array: Array<Optional<T>>) -> Array<T> { ... } になりますが、関数だと記述順が辛いところをfunc |> (a, b) { return b(a) }public typealias BilinearForm<V: VectorSpace> = BilinearMap<V, V, AsVectorSpace<V.CoeffRing>> extension BilinearForm: BilinearFormType where Domain: ProductSetType & VectorSpace, Domain.Left: VectorSpace, Domain.Left == Domain.Right, Domain.CoeffRing == Domain.Left.CoeffRing, Codomain == AsVectorSpace<Domain.CoeffRing> { }typealias に対して extension を書かない方がいいかもしれませんね。class C<T> {} typealias IntC = C<Int> extension IntC {}Swift version 4.1 (swift-4.1-RELEASE)/usercode/main.swift:3:1: error: constrained extension must be declared on the unspecialized generic type 'C' with constraints specified by a 'where' clause extension IntC {} ^ ~~~~ #if swift(>=4.1.0) let version = "4.1.0" #elsif swift(>=4.0.3) // it should be `elseif` let version = "4.0.3" #endifSwift version 4.1 (swift-4.1-RELEASE)/usercode/main.swift:3:9: error: expected expression #elsif swift(>=4.0.3) // it should be `elseif` ^ /usercode/main.swift:4:17: error: invalid redeclaration of 'version' let version = "4.0.3" ^ /usercode/main.swift:2:17: note: 'version' previously declared here let version = "4.1.0" ^ #if swift(>=4.1.0) let version = "4.1.0" #elsif swift(>=4.0.3) // it should be `elseif` let version = "4.0.3" #endifSwift version 4.1 (swift-4.1-RELEASE)error: failed to launch REPL process: process launch failed: 'A' packet returned an error: 8 #if swift(>=4.1.0) let version = "4.1.0" #elsif swift(>=4.0.3) // it should be `elseif` let version = "4.0.3" #endifSwift version 4.1 (swift-4.1-RELEASE)-swift-version 3が付いた時に#elsifってのがそのまま通ってしまうぽい?#if から #endif の間が swift(>=4.1.0) じゃないので、パースの対象外になるので、_ = version書いとけば判定はできそうですね。 一般的には使えなそうですが。-swift-version 3 でも 4.2 対応のコンパイラなら swift(>=4.1.0) は false だけども内容はパースする。canImport()とかの新しい条件が含まれてた時にエラーになったりしないですかね。つまり -swift-version 3 でも 4.2 対応のコンパイラなら swift(>=4.1.0) は false だけども内容はパースする。 コードが想定する対応バージョンのコンパイラでちゃんとテストしろ、で済んでしまう問題ではあるのですよね…extension Optional { public func unwrap(_ message: @autoclosure () -> String = "", file: StaticString = #file, line: UInt = #line) -> Wrapped { guard let value = self else { let m = message() fatalError("Optional unwrap failed" + (!m.isEmpty ? ": " + m : ""), file: file, line: line) } return value }guard let tableView = tableViewController.tableView else { fatalError("UITableViewControllerじゃなくなった?") }let tableView = tableViewController.tableView.unwrap("UITableViewControllerじゃなくなった?") ↑こうかいたほうがよくない?!とか、死ぬケースっていうのは、把握しておく必要はないはずなんだよね!相当のクラッシュとかは、メソッド冒頭に集めてあるイメージではあるfunc preconditionNotNone<T>(_ t: T?) -> T let x = a.x * b.x - a.y * b.y - a.z * b.z - a.w * b.w が Expression was too complex... と言われて辛いlet x = a.x * b.x - (a.y * b.y + a.z * b.z + a.w * b.w)true && true && true とかやるだけで出てた気がするのでだいぶ良くはなったんだと思いますがx, y, z, w の型が定まってるなら組み合わせなさそうですけどねーExpressibleByXxxLiteral で組み合わせ爆発するけど(ここが Swift 特有の問題だと思ってます)、この場合はどうしてだろう・・・。 (edited) public static func -(a: 𝐑, b: 𝐑) -> 𝐑 { return 𝐑(a.value - b.value, a.error + b.error) }(a.x * b.x )- (a.y * b.y) - (a.z * b.z) - (a.w * b.w) の - を探し続けてたってこと? (edited)swift -frontend -typecheck -debug-constraints ファイル名.swift で見れます )public extension AdditiveGroup { public static func -(a: Self, b: Self) -> Self { return (a + (-b)) } }
https://github.com/taketo1024/SwiftyMath/blob/master/Sources/SwiftyMath/Abstract/AdditiveGroup.swift#L12let x = a.x * b.x + -a.y * b.y - a.z * b.z - a.w * b.wswift -frontend -typecheck -debug-constraints って簡単なコードでもすごい大量の出力がありますね。protocol FooProtocol { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self static prefix func-(value: Self) -> Self } extension FooProtocol { static func -(lhs: Self, rhs: Self) -> Self { return lhs + -rhs } } struct Foo : FooProtocol { static func +(lhs: Foo, rhs: Foo) -> Foo { return lhs } static prefix func-(value: Foo) -> Foo { return value } } let a = Foo() let b = a + a - a + a - a + a - a + aprotocol FooProtocol { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self static prefix func-(value: Self) -> Self } extension FooProtocol { static func -(lhs: Self, rhs: Self) -> Self { return lhs + -rhs } } struct Foo : FooProtocol { static func +(lhs: Foo, rhs: Foo) -> Foo { return lhs } static prefix func-(value: Foo) -> Foo { return value } } let a = Foo() let b = a + a - a + a - a + a - a + aprotocol FooProtocol { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self static prefix func-(value: Self) -> Self } extension FooProtocol { static func -(lhs: Self, rhs: Self) -> Self { return lhs + -rhs } } struct Foo : FooProtocol { static func +(lhs: Foo, rhs: Foo) -> Foo { return lhs } static prefix func-(value: Foo) -> Foo { return value } } extension Foo { static func -(lhs: Foo, rhs: Foo) -> Foo { return lhs + -rhs } } let a = Foo() let b = a + a - a + a - a + a - a + a- はデフォルト実装だからじゃないですか?prefix の可能性もあるのか。prefix と解釈したらパースに失敗しそうな?+ か - かどっちかは明示的な実装が必要でないですか?let x = a.x * b.x - a.y * b.y - a.z * b.z// - a.w * b.wprotocol FooProtocol { static func +(lhs: Self, rhs: Self) -> Self static func -(lhs: Self, rhs: Self) -> Self } extension FooProtocol { static func -(lhs: Self, rhs: Self) -> Self { return lhs + rhs } } struct Foo : FooProtocol { static func +(lhs: Foo, rhs: Foo) -> Foo { return lhs } } let a = Foo() let b = a + a - a + a - a + a - a + a@availableを使える様にしてもらった。 https://bugs.swift.org/browse/SR-7201.app 形式にうまくパッケージされない気が@testable import MainApp したらMainApp側の型がコード補完上見れるようになったところまではやったEXCLUDED_SOURCE_FILE_NAMES=AppDelegate.swift と書きつつ、 TestAppDelegate.swift というのだけ追加すればいいのではないかしら。 (edited)let viewController = ... let window = UIWindow() window.backgroundColor = .white window.rootViewController = viewController window.makeKeyAndVisible() RunLoop.main.run(until: Date(timeIntervalSinceNow: 0)) viewController.view.layer.render() ^ みたいなことをした方が簡単。Processで起動した子プロセスの出力をキャプチャする際にはDispatchGroupで待つと良いという知見を得た。 https://github.com/norio-nomura/SwiftCompilerDiscordappBot/blob/master/Sources/SwiftCompilerDiscordappBot/execute().swift#L27-L31dequeueReusableCell(withReuseIdentifier:for:)でインスタンス化を行うため、そもそもコンストラクタのカスタマイズはできないものなのでしょうか?let cell = collectionView.dequeueReusableCell(with: FilterCell.self, for: indexPath) cell.configure(image: image, name: name) 内包する案もよさそうですね、ありがとうございます*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'the cell returned from -collectionView:cellForItemAtIndexPath: does not have a reuseIdentifier - cells must be retrieved by calling -dequeueReusableCellWithReuseIdentifier:forIndexPath:'message2でだけas [String : Any]が必要だと言われるのだろう? @swift-4.1.3
let content = "" let fields = [["name": "stdout.txt", "value": ""]] let message1 = fields.isEmpty ? ["content": content] : ["content": content, "embed": ["fields": fields]] let message2 = ["content": content, "embed": ["fields": fields]]main.swift:4:16: error: heterogeneous collection literal could only be inferred to '[String : Any]'; add explicit type annotation if this is intentional let message2 = ["content": content, "embed": ["fields": fields]] ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ as [String : Any]message1も同じ型になるのに。dynamicMemberLookup 把握。subscript(dynamicMember:)の実装を必要とするアトリビュートなんだね。 @swift-4.2.4
@dynamicMemberLookup indirect enum UID: CustomStringConvertible { case root(String) case leaf(parent: UID, String) subscript(dynamicMember member: String) -> UID { return .leaf(parent: self, member) } var description: String { switch self { case .root(let string): return string case .leaf(let parant, let string): return "\(parant).\(string)" } } } let root = UID.root("root") print(root.a.b.c)extension Matrix: Codable where R: Codable { //Implementation of 'Decodable' cannot be automatically synthesized in an extensionstruct を作れば解決する気がします。Array も Element が Codable なときだけ Codable になりましたextension Array : Codable where Element : Codable { ... }let elements = try container.decode([A : R].self, forKey: .elements) (edited)CGAffineTransform の逆行列は transform.inverted() なのに、 ARKit 等で使う simd の matrix_float4x4 の逆行列は matrix.inverse になってる・・・CGAffineTransform はかけ算も concatenating だし、基本的に行列として扱わないネーミングなのかな? (edited)Vector2 を Codable にして JSON に変換すると {"x":2,"y":3} のように出力させる実装をする 2. Library A の中で Vector2 を持つ struct Foo : Codable を作る 3. Library A を使う App B を作る 4. App B のあるファイルで Library A を import せず に Vector2 を Codable にして JSON に変換すると [2, 3] のように出力させる実装をする 5. App B の別のファイルで Library A を import して Vector2 を JSON に変換すると [2, 3] 、 Foo を JSON に変換するとその中の Vector2 は {"x":2,"y":3} というのができた。 (edited)Vector2 に二通りの Codable の実装をして、それぞれ呼び分けることができた。なんとなくできない気がしてたけど、問題なかった。 (edited)import で Codable の実装を切り替えたりできそうですね。Codable に限りませんが)import LibraryA をせずに Vector2 を持つ struct を Codable にしようとしたらエラーになったから、これはと思って試したんだけどimport LibraryA せずに Vector2 を持つ struct が Codable にできるようになってしまった。逆に Codable を付けようとすると redundant でエラーになる・・・。 (edited)[omochi@omochi-iMacPro k (master=)]$ cat Sources/App/main.swift import Nature import Japan import US var animals: [AnimalProtocol] = [] animals.append(createJapanCat()) animals.append(createUSCat()) animals.forEach { animal in print(animal.speak()) } [omochi@omochi-iMacPro k (master=)]$ swift run にゃあ meow&+ ならオーバーフローしても落ちないですfunc addingReportingOverflow(_ other: Int) -> (partialValue: Int, overflow: Bool)addWithOverflow の名前が変わったんですね infix operator %+ struct E : Error {} func %+(a: UInt32, b: UInt32) throws -> UInt32 { let c = a.addingReportingOverflow(b) if c.overflow { throw E() } return c.partialValue } try UInt32(0x80_00_00_00) %+ UInt32(0x80_00_00_00)Swift version 4.1 (swift-4.1-RELEASE)/usercode/main.swift:11:27: warning: result of operator '%+' is unused try UInt32(0x80_00_00_00) %+ UInt32(0x80_00_00_00) ~~~~~~~~~~~~~~~~~~~~~ ^ ~~~~~~~~~~~~~~~~~~~~~ Fatal error: Error raised at top level: main.E(): file /home/buildnode/jenkins/workspace/oss-swift-4.1-package-linux-ubuntu-16_04/swift/stdlib/public/core/ErrorType.swift, line 191 Current stack trace: 0 libswiftCore.so 0x00007f8e1fc285c0 _swift_stdlib_reportFatalErrorInFile + 221 1 libswiftCore.so 0x00007f8e1f9973dc <unavailable> + 1369052 2 libswiftCore.so 0x00007f8e1fbd1222 <unavailable> + 3703330 3 libswiftCore.so 0x00007f8e1fbd2689 <unavailable> + 3708553 4 libswiftCore.so 0x00007f8e1f996ad6 <unavailable> + 1366742 5 libswiftCore.so 0x00007f8e1fbd0feb <unavailable> + 3702763 6 libswiftCore.so 0x00007f8e1f996ad6 <unavailable> + 1366742 7 libswiftCore.so 0x00007f8e1fb03f79 <unavailable> + 2862969 8 libswiftCore.so 0x00007f8e1f9d4960 swift_errorInMain + 318 10 swift 0x0000000000fed1ce <unavailable> + 12505550 11 swift 0x0000000000ff1692 <unavailable> + 12523154 12 swift 0x00000000004d9076 <unavailable> + 888950 13 swift 0x00000000004c35d3 <unavailable> + 800211 14 swift 0x00000000004beecc <unavailable> + 782028 15 swift 0x00000000004778c4 <unavailable> + 489668 16 libc.so.6 0x00007f8e22141740 __libc_start_main + 240 17 swift 0x0000000000475179 <unavailable> + 479609 /usr/bin/swift[0x3f24d54] /usr/bin/swift[0x3f25096] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7f8e23a17390] ...array[i] などと同じく API 設計上の意図的なものだと思うので。 (edited)let o1 = tanh(x ⊗ w1 + b1) 内積演算子(テンソル積演算子?)、どうやって入力するんだろう.. (edited)import TensorFlow let x = Tensor<Float>(shape: [1, 2], repeating: 0.1) let y = Tensor<Float>(shape: [3, 4], repeating: 0.1) let matmul = x ⊗ y print(matmul)
test.swift:5:16: error: internal error generating TensorFlow graph: Dimensions must be equal, but are 2 and 3 for 'op.test.swift.5.16' (op: 'MatMul') with input shapes: [1,2], [3,4]. let matmul = x ⊗ y (edited)import TensorFlow let x = Tensor<Float>(shape: [1, 2], repeating: 0.1) let y = Tensor<Float>(shape: [3, 4], repeating: 0.1) let matmul = x ⊗ y print(matmul)main.swift:4:21: error: internal error generating TensorFlow graph: GraphGen cannot lower a 'receive' from the host yet let y = Tensor<Float>(shape: [3, 4], repeating: 0.1) ^~/Library/Developer/Xcode/UserData/ に入れればすぐ出ます。 (edited)function (lhs ... ) { ... }JSONEncoder.KeyEncodingStrategy.convertToSnakeCaseとJSONDecoder.KeyDecodingStrategy.convertFromSnakeCaseが非対称となる問題のスレッドがSwift Forumではじまりました。 https://forums.swift.org/t/handling-edge-cases-in-jsonencoder-jsondecoder-key-conversion-strategies-sr-6629/12384
import Foundation struct S: Codable { var myURLProperty: String } let encoder = JSONEncoder() encoder.keyEncodingStrategy = .convertToSnakeCase let data = try encoder.encode(S(myURLProperty: "property")) let decoder = JSONDecoder() decoder.keyDecodingStrategy = .convertFromSnakeCase let decoded = try decoder.decode(S.self, from: data) // "No value associated with key CodingKeys(stringValue: \"myURLProperty\", intValue: nil) (\"myURLProperty\"), converted to my_url_property."
上記コードはLinuxでは動きません。 (edited)swiftの標準入力へソースコードを渡して実行させる時、-以降をCommandLine.argumentsとして取り出せるのね。 $ echo 'dump(CommandLine.arguments)' | swift -Onone - -verbose ▿ 2 elements - "-" - "-verbose"▿ 2 elements - "-" - "-verbose"UserDefaults.argumentDomainサポートは4.2から。 @swift-4.1.3 @swift-4.2.4 - -param1 yes import Foundation print(CommandLine.arguments) print("param1: \(UserDefaults.standard.bool(forKey: "param1"))")["-", "-param1", "yes"] param1: true["-", "-param1", "yes"] param1: falseprotocol A{} struct S<X> {} extension S: A where X == Int {} extension S: A where X == String {}protocol A{} struct S<X> {} extension S: A where X == Int {} extension S: A where X == String {}swift-4.1.1-RELEASE/usercode/main.swift:4:14: error: redundant conformance of 'S<X>' to protocol 'A' extension S: A where X == Int {} ^ /usercode/main.swift:5:1: note: 'S<X>' declares conformance to protocol 'A' here extension S: A where X == String {} ^protocol IntOrString {} extension Int : IntOrString {} extension String : IntOrString {} extension S: A where X: IntOrString {}enum AorB { case a(A) case b(B) } protocol AorBProtocol { var _value: AorB { get } } extension A: AorBProtocol { var _value: AorB { return .a(self) } extension B: AorBProtocol { var _value: AorB { return .b(self) } extension Array: Foo where Element: AorBProtocol { func fooFunc() { forEach { switch $0._value { case .a(let a): // write a case here case .b(let b): // write b case here } } } } (edited)protocol A1 {} protocol A2: A1 {} protocol A3: A2 {} struct C<R>: A1 extension C: A2, A3 where R == X extension C: A2 where R == Y (edited)Complex<R> にして、複素数体 C = Complex<Real> と ガウス整数環 Complex<Int> を共通化しようとしまして、 (edited)protocol XorY {} struct X: XorY {} struct Y: XorY {} protocol A1 {} protocol A2: A1 {} protocol A3: A2 {} struct C<R>: A1 { } extension C: A2 where R: XorY { } extension C: A3 where R == Y { }protocol XorY {} struct X: XorY {} struct Y: XorY {} protocol A1 {} protocol A2: A1 {} protocol A3: A2 {} struct C<R>: A1 { } extension C: A2 where R: XorY { } extension C: A3 where R == Y { }swift-4.1.1-RELEASEprotocol XorY {} struct X: XorY {} struct Y: XorY {} protocol A1 { func a1() -> String } protocol A2: A1 { func a2() -> String } protocol A3: A2 { func a3() -> String } struct C<R>: A1 { func a1() -> String { return "a1\(R.self)" } } extension C: A2 where R: XorY { func a2() -> String { return "a2\(R.self)" } } extension C: A3 where R == Y { func a3() -> String { return "a3\(R.self)" } } print(C<X>().a1()) print(C<X>().a2()) // print(C<X>().a3()) // compile error print(C<Y>().a1()) print(C<Y>().a2()) print(C<Y>().a3()) シンプルな例ならイケそうな雰囲気はありますが…もしかしたら別のところでダメなのかも (edited)protocol XorY {} struct X: XorY {} struct Y: XorY {} protocol A1 { func a1() -> String } protocol A2: A1 { func a2() -> String } protocol A3: A2 { func a3() -> String } struct C<R>: A1 { func a1() -> String { return "a1\(R.self)" } } extension C: A2 where R: XorY { func a2() -> String { return "a2\(R.self)" } } extension C: A3 where R == Y { func a3() -> String { return "a3\(R.self)" } } print(C<X>().a1()) print(C<X>().a2()) // print(C<X>().a3()) // compile error print(C<Y>().a1()) print(C<Y>().a2()) print(C<Y>().a3())swift-4.1.1-RELEASEa1X a2X a1Y a2Y a3Ypublic typealias 𝐑 = RealNumberenum AorB { case a(A) case b(B) } protocol AorBProtocol { var _value: AorB { get } } すいません、こちらはちょっと理解が不十分でした、public protocol ComplexType: Ring { associatedtype Base: Ring init(_ x: Base) init(_ x: Base, _ y: Base) static var imaginaryUnit: Self { get } var realPart: Base { get } var imaginaryPart: Base { get } var inverse: Self? { get } var conjugate: Self { get } } ってして、 protocol extension つける方向で行こうかと思いますextension Array: Equatable where Element==Int {} (edited)extension Array: Equatable where Element==Int {}swift-4.1.1-RELEASE/usercode/main.swift:1:18: warning: conformance of 'Array<Element>' to protocol 'Equatable' was already stated in the type's module 'Swift' extension Array: Equatable where Element==Int {} ^ Swift.Array<Element>:1:11: note: 'Array<Element>' declares conformance to protocol 'Equatable' here extension Array : Equatable where Element : Equatable { ^extension Array: Equatable where Element==Never { static func == (lhs: Array, rhs: Array) -> Bool { return true } } (edited)extension Array: Equatable where Element==Never { static func == (lhs: Array, rhs: Array) -> Bool { return true } }extension Array: Equatable where Element==Never { static func == (lhs: Array, rhs: Array) -> Bool { return true } }swift-4.1.1-RELEASE/usercode/main.swift:1:18: warning: conformance of 'Array<Element>' to protocol 'Equatable' was already stated in the type's module 'Swift' extension Array: Equatable where Element==Never { static func == (lhs: Array, rhs: Array) -> Bool { return true } } ^ /usercode/main.swift:1:63: note: operator function '==' will not be used to satisfy the conformance to 'Equatable' extension Array: Equatable where Element==Never { static func == (lhs: Array, rhs: Array) -> Bool { return true } } ^ Swift.Array<Element>:1:11: note: 'Array<Element>' declares conformance to protocol 'Equatable' here extension Array : Equatable where Element : Equatable { ^#if swift(>=4.2) print("swift-4.2") #elseif swift(>=4.1.50) print("swift-4.1.50") #elseif swift(>=4.1.2) print("swift-4.1.2") #endifSwift version 4.2-dev (LLVM a38ff55b31, Clang 5272858825, Swift defc3e9073) Target: x86_64-unknown-linux-gnu (edited)nil パターンのテスト書かなくて済むメリットがあるのかなという意味です¬AutoLayout は多分そもそもGitHubでリポジトリ作れないしCartfileとかで指定できなさそうな気が let f = Float.nan let a = [f] let b = [f] print(f == f) // false print(a == a) // true print(a == b) // falselet f = Float.nan let a = [f] let b = [f] print(f == f) // false print(a == a) // true print(a == b) // falseswift-4.1.1-RELEASEfalse true falseprint(Float.nan == Float.nan) (edited)let f = Float.nan let a = Optional(f) let b = Optional(f) print(f == f) // false print(a == a) // false print(a == b) // falselet f = Float.nan let a = Optional(f) let b = Optional(f) print(f == f) // false print(a == a) // false print(a == b) // falseswift-4.1.1-RELEASEfalse false falseDictionary や Set もおかしくなるんじゃない?Optional は中身が一つしかないからそれの == を使うだろうけど、 Dictionary や Set だと Array と同じショートカットが行われてそう。Array のバグなのか、 Float の(というか IEEE の)問題なのか。Equatable なのに equality じゃなくて equivalence なのか・・・。英語むずい・・・。Float の == を変えるのも難しいよね・・・。Array 等のショートカットをやめる 3. Float 等の == を変える だけど。結局 1 にしかならなさそう。var d: [Float: String] = [:] d[.nan] = "a" d[.nan] = "b" d[.nan] = "c" print(d.count) print(d[.nan]) print(d == d)var d: [Float: String] = [:] d[.nan] = "a" d[.nan] = "b" d[.nan] = "c" print(d.count) print(d[.nan]) print(d == d)swift-4.1.1-RELEASE3 nil true/usercode/main.swift:6:7: warning: expression implicitly coerced from 'String?' to Any print(d[.nan]) ^~~~~~~ /usercode/main.swift:6:8: note: provide a default value to avoid this warning print(d[.nan]) ~^~~~~~ ?? <#default value#> /usercode/main.swift:6:8: note: force-unwrap the value to avoid this warning print(d[.nan]) ~^~~~~~ ! /usercode/main.swift:6:8: note: explicitly cast to Any with 'as Any' to silence this warning print(d[.nan]) ~^~~~~~ as Any&== を IEEE 754 に従った素の計算にして、 == だと反射率を満たすようにすればいい気が。&== 入れるなら == がIEEEに従う じゃないですか?== は Equatable で規定されるものだから、 Equatable の == が反射率を満たす必要があることを明記して&== は &+ 等と同様の余分なオーバーヘッドのない計算をしてくれる演算子でいいのでは?true でいいんじゃないかなぁ== .nan を見て、このコードバグってんぞ→バグってなかった!ってなりそうInt の + だってそうでしょ?Float や Double の == より Int の + を使う機会の方がずっと多いのでは?+ や * は使っても == はそんなに使わなさそう。Float や Double で、 CPU 上で計算してる時点でパフォーマンスにこだわるケースじゃなさそう。Equatable はあくまで計算結果の値についてなので、成り立つように思います。Equatable はあくまで値についての性質なので、どのような式で nan が導かれても推移律は満たされることになるかと。a == aのケースについて話されてるかはこれから読みます。Array.== first looks to referential equality of underlying buffer...Array.== first looks to referential equality of underlying Element.==. As a consequence, an array of NaN compares equal to another array of NaN if they share the same buffer, but otherwise false. This is an undesirable outcome. 頭から書いてあったThe last time that this topic was brought up, competing demands voiced by different people were not possible to reconcile: 1) Equatable `==` must be a full equivalence relation. 2) Floating-point types must conform to `Equatable` and not to some alternative such as `PartiallyEquatable`. 3) Floating-point `==` must be IEEE-compliant (at least in the concrete context), and therefore *not* a full equivalence relation. 4) IEEE-compliant floating-point equivalence must be spelled `==` and not some alternative such as `&==`. 5) Behavior of `==` must not change between generic and concrete contexts.protocol A { static func hoge() } struct B: A { static func hoge() { print("B") } } extension Optional: A where Wrapped: A { static func hoge() { print("Optional") } } struct F<T> { static func fuga() { switch T.self { case is A.Type: (T.self as! A.Type).hoge() default: fatalError() } } } F<B>.fuga() // B // warning: Swift runtime does not yet support dynamically querying conditional conformance F<B?>.fuga() // fatalError (edited)swift-4.2-DEVELOPMENT-SNAPSHOT-2018-04-23-aHList を HCons と HNil に限定できないのが辛いですね。 enum でも書けなさそうだし・・・。List なら↓みたいに書けるんですけどね〜。 enum List<Element> { case `nil` indirect case cons(Element, List<Element>) } let a: List<Int> = .cons(2, .cons(3, .cons(5, .nil))) (edited)enumが型パラメータを取れないと無理なんですよね……。canImportはimportの様にシンボルを使う事は出来ないのか…。 @swift-main
import Foundation let killSignals: [Int32] = { var signals = [SIGILL, SIGTRAP, SIGABRT, SIGFPE, SIGBUS, SIGSEGV, SIGQUIT] #if canImport(Glibc.SIGSYS) signals.append(Glibc.SIGSYS) #endif return signals }() (edited)<stdin>:4:5: error: unexpected platform condition argument: expected identifier #if canImport(Glibc.SIGSYS) ^ (edited)public struct Uniform { var base: RandomNumberGenerator init(base: RandomNumberGenerator) { self.base = base } /// Returns a value from uniform [low, high) distribution. public mutating func next(low: Float, high: Float) -> Float { let uint32: UInt32 = base.next() return (high - low) * (Float(bitPattern: uint32 >> 9 | 0x3f80_0000) - 1) + low } } extension RandomNumberGenerator { public var uniform: Uniform { return Uniform(base: self) } } こういうの作ろうと思ったんですがRNGがstructだと内部状態コピーされるから微妙ですね…… (edited)next(range: Range<Float>) を RandomNumberGenerator に生やすとか?extension で追加してもいい気も (edited)next(range: Range<Float>)とnext(mu: Float, sigma: Float)だと分かりづらくないですかね?Random は struct だけどそれは起こらないのと、struct の場合var a = FooRandom() var b = a a.next() == b.next() // true になるんだから、 Uniform もそれでいいんじゃないかな?var a = FooRandom() print(a.uniform.next(...) print(a.uniform.next(...) これで同じのが出るのが嫌か。uniform を get set なプロパティにしてBool の toggle とかと同じように元の struct に変更を反映できない?set で base を self に代入すればいいのか。 (edited)swift public struct Uniform { var base: RandomNumberGenerator init(base: RandomNumberGenerator) { self.base = base } /// Returns a value from uniform [low, high) distribution. public mutating func next(low: Float, high: Float) -> Float { print("base before; \(base)") let uint32: UInt32 = base.next() print("base after; \(base)") return (high - low) * (Float(bitPattern: uint32 >> 9 | 0x3f80_0000) - 1) + low } } extension RandomNumberGenerator { public var uniform: Uniform { get { return Uniform(base: self) } set { print("before set: \(self)") self = uniform.base as! Self print("set self: \(self) \(uniform.base)") } } } struct DummyRNG: RandomNumberGenerator { static var `default` = DummyRNG.init() var state: UInt32 = 0 mutating func next<T>() -> T where T : FixedWidthInteger, T : UnsignedInteger { state += 123456789 return T(state) } } print(DummyRNG.default.uniform.next(low: 0, high: 1)) print(DummyRNG.default.uniform.next(low: 0, high: 1)) print(DummyRNG.default.uniform.next(low: 0, high: 1))base before; DummyRNG(state: 0) base after; DummyRNG(state: 123456789) before set: DummyRNG(state: 0) set self: DummyRNG(state: 0) DummyRNG(state: 0) 0.02874446 base before; DummyRNG(state: 0) base after; DummyRNG(state: 123456789) before set: DummyRNG(state: 0) set self: DummyRNG(state: 0) DummyRNG(state: 0) 0.02874446 base before; DummyRNG(state: 0) base after; DummyRNG(state: 123456789) before set: DummyRNG(state: 0) set self: DummyRNG(state: 0) DummyRNG(state: 0) 0.02874446Uniform<Random : RandomNumberGenerator> にした方が Swifty じゃないですか?base を fileprivate にする PR 送ろうかと思ったら、逆に 1.0.0 から 1.0.1 で internal → public な変更がされてるんですが、この意図は何でしょう?1.0.0 → 1.1.0 の変更だと思います。-alpha や -beta, -beta.2 等を付けておくのがオススメです。1.0.0 から始めずに 0.1.0 から始めた方が気軽に破壊的変更しやすいです。)base を外部から使ってなくないですか? https://github.com/t-ae/xorswift/blob/swift4.2/Sources/Uniform.swiftbase.xとかが出てきます.base で検索してたFloat.random(in:)がありましたね。 normalもこっちの形式に揃えるほうがいいんだろうか……strings.compactMap(Int.init) で、 flatMap 以前なので 3 週古くて(リネーム前の flatMap → Array を返す flatmap → reduce)reduce 使うにしても今だったら reduce(into:_:) だし。let a = [[2], [3 ,5]] for var (i, numbers) in a.enumerated() { numbers.append(3) print("\(i): \(numbers)") }let a = [[2], [3 ,5]] for var (i, numbers) in a.enumerated() { numbers.append(3) print("\(i): \(numbers)") }swift-4.1.1-RELEASE0: [2, 3] 1: [3, 5, 3]/usercode/main.swift:3:10: warning: variable 'i' was never mutated; consider changing to 'let' constant for var (i, numbers) in a.enumerated() { ^numbers は var に、 i は let にしたい。let a = [[2], [3 ,5]] for (i, var numbers) in a.enumerated() { numbers.append(3) print("\(i): \(numbers)") }let a = [[2], [3 ,5]] for (i, var numbers) in a.enumerated() { numbers.append(3) print("\(i): \(numbers)") }swift-4.1.1-RELEASE0: [2, 3] 1: [3, 5, 3]var と let に bind したい。 @swiftbot
let a = [[2], [3 ,5]] var iterator = a.enumerated().makeIterator() if var (i, numbers) = iterator.next() { numbers.append(0) print("\(i): \(numbers)") }let a = [[2], [3 ,5]] var iterator = a.enumerated().makeIterator() if var (i, numbers) = iterator.next() { numbers.append(0) print("\(i): \(numbers)") }swift-4.1.1-RELEASE0: [2, 0]/usercode/main.swift:4:9: warning: variable 'i' was never mutated; consider changing to 'let' constant if var (i, numbers) = iterator.next() { ^if case (let i, var numbers)? = iterator.next() {case にしちゃえばいいのか。ありがとうございます!_random()をrandom(in: UnboundedRange)にしたら?って提案しようかと思うんですがこういう細かい&そもそもまだ固まってない内容もフォーラムにスレッド立てていいんですかね? RandomUnificationのスレはちょっと古くて……random(in: UnboundedRange) は新しい API の提案だし、 reduce(into:_:) や toggle 、 compactMapValues を考えると、単独の API の提案は全然ありな気がします。FixedWidthInteger に限らず検討することになるかもしれないにしても、 pitch は気軽に投げていいんじゃないでしょうか。struct Foo { var bar: Bar { mutating get { ... } } } ↓に書き換えた方がいいでしょうか? struct Foo { mutating func bar() -> Bar { ... } }get されてから lazy に読み込んでキャッシュしたいケースです。var foo1 = Foo() var foo2 = foo1 var bar = foo2.bar というときに、foo1 にキャッシュが共有されないというのが許容出来る場合、僕なら mutating func bar() にします。class にするか、グローバルにキャッシュを持つしかない。protocol P { associatedtype T func f(_ g: @escaping (T) -> Void) } class C<S>: P { typealias T = S private let _f: ((S) -> Void) -> Void init<Q: P>(q: Q) where Q.T == T { // Error: cannot assign value of type '((S) -> Void) -> Void' to type '((S) -> Void) -> Void' self._f = { g -> Void in q.f(g) } } func f(_ g: @escaping (S) -> Void) { self._f(g) } }protocol P { associatedtype T func f(_ g: @escaping (T) -> Void) } class C<S>: P { typealias T = S private let _f: (@escaping (S) -> Void) -> Void init<Q: P>(q: Q) where Q.T == T { // Error: cannot assign value of type '((S) -> Void) -> Void' to type '((S) -> Void) -> Void' self._f = { g -> Void in q.f(g) } } func f(_ g: @escaping (S) -> Void) { self._f(g) } }cannot assign value of typeのエラーわかりにくい問題、最新のXcodeだと治ってて一発でわかりますよ@escaping入れなきゃいけない位置を秒で特定できたのはちょい謎@escaping必要だって、、わいのXcodeは表示したんや…そのはずや…self の再宣言で LLDB 壊れますね class Example { func ok() { let f = { [weak self] in guard let strongSelf = self else { return } // Set a breakpoint at here print(strongSelf) } f() } func error() { let f = { [weak self] in guard let `self` = self else { return } // Set a breakpoint at here print(self) } f() } } Example().ok() Example().error()(lldb) br set --file example.swift --line 7 Breakpoint 1: where = example`closure #1 () -> () in example.Example.ok() -> () + 111 at example.swift:7, address = 0x00000001000017df (lldb) br set --file example.swift --line 18 Breakpoint 2: where = example`closure #1 () -> () in example.Example.error() -> () + 111 at example.swift:18, address = 0x00000001000019cf (lldb) r Process 6298 launched: '/Users/yuki.kokubun/Development/self-self-lldb/example' (x86_64) Process 6298 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 1.1 frame #0: 0x00000001000017df example`closure #1 in Example.ok(self=0x0000000100802b30) at example.swift:7 4 guard let strongSelf = self else { return } 5 6 // Set a breakpoint at here -> 7 print(strongSelf) 8 } 9 10 f() Target 0: (example) stopped. (lldb) po self ▿ Optional<Example> - some : <Example: 0x100802b30> (lldb) c Process 6298 resuming example.Example Process 6298 stopped * thread #1, queue = 'com.apple.main-thread', stop reason = breakpoint 2.1 frame #0: 0x00000001000019cf example`closure #1 in Example.error(self=0x0000000100a01030) at example.swift:18 15 guard let `self` = self else { return } 16 17 // Set a breakpoint at here -> 18 print(self) 19 } 20 21 f() Target 0: (example) stopped. (lldb) po self error: warning: <EXPR>:12:9: warning: initialization of variable '$__lldb_error_result' was never used; consider replacing with assignment to '_' or removing it var $__lldb_error_result = __lldb_tmp_error ~~~~^~~~~~~~~~~~~~~~~~~~ _ error: <EXPR>:18:5: error: value of type 'Example' has no member '$__lldb_wrapped_expr_2' $__lldb_injected_self.$__lldb_wrapped_expr_2( ^~~~~~~~~~~~~~~~~~~~~ ~~~~~~~~~~~~~~~~~~~~~~fr var は下のようになるので単純な名前ベースでの解決をしようとすると死ぬのが原因…? (lldb) fr var (@lvalue example.Example?) self = 0x0000000100a01030 (example.Example) self = 0x0000000100a01030 {}self?. で書くか、 クロージャの中で必要な変数をそれぞれguardでアンラップする、って感じに最近はしてますね。guard let `self` = self else { return } ^ のところをselfじゃなくて、selfの先を3〜4つアンラップする感じd。guard let self = self else { return } <= これは見た目美しいけどトラブルが多いので良くない、 strongSelf <= これは人によって色々だしどう書いても美しくない、Error のインスタンスが手元にあるときに、それでクラッシュさせる ( try! に失敗したのと同じ状態にする)簡単な方法ってありますっけ? fatalError("\(error)") でもいいのかもしれませんが、 Error から String に情報が落ちてしまってますし。try! throw errortry ! { throw error }() だと Never でないので guard で使えないですし。try! throw error は throw が関数じゃないからできなくない?internal func fatalError<E: Error>(with error: E) -> Never { try! { throw error }() fatalError("Never reaches here.") } という微妙なユーティリティ関数を作ろうとしたけどもっといい方法はないかなと。throw new RuntimeException(exception); とかでいいんだけど。fatalError じゃなくて preconditionFailure がいいかな。 precondition なのか微妙だけど。)String(reflecting: error) で同等みたいです。_unexpectedError の返り値の型は Never ではないのですねCMSampleBufferGetImageBuffer(_:) みたいな関数群があるけど https://developer.apple.com/documentation/coremedia/1489236-cmsamplebuffergetimagebufferDispatchQueue.global(qos: .default).async { // この中で [NSException raise] が呼ばれていて、 // breakpoint set -S raise で止まった状態を想定してください。 // ここで、この doSomething を呼び出す task を誰が追加したのか // 追跡したい感じです。 doSomething() }(lldb) th backtrace * thread #3, queue = 'com.apple.root.default-qos', stop reason = breakpoint 1.1 frame #0: 0x000000010e89e001 libobjc.A.dylib`objc_exception_throw frame #1: 0x000000010f2090b9 CoreFoundation`-[NSException raise] + 9 * frame #2: 0x000000010df90ea6 StackChain`doInnerSomething() at ViewController.swift:8 frame #3: 0x000000010df90e19 StackChain`doSomething() at ViewController.swift:4 frame #4: 0x000000010df910c9 StackChain`closure #1 in ViewController.onButton() at ViewController.swift:14 frame #5: 0x000000010df910fd StackChain`thunk for @escaping @callee_guaranteed () -> () at ViewController.swift:0 frame #6: 0x000000011359b7ab libdispatch.dylib`_dispatch_call_block_and_release + 12 frame #7: 0x000000011359c7ec libdispatch.dylib`_dispatch_client_callout + 8 frame #8: 0x00000001135a1619 libdispatch.dylib`_dispatch_queue_override_invoke + 1451 frame #9: 0x00000001135a836c libdispatch.dylib`_dispatch_root_queue_drain + 664 frame #10: 0x00000001135a8076 libdispatch.dylib`_dispatch_worker_thread3 + 132 frame #11: 0x0000000113ac7169 libsystem_pthread.dylib`_pthread_wqthread + 1387 frame #12: 0x0000000113ac6be9 libsystem_pthread.dylib`start_wqthread + 13 (lldb) thread backtrace -e trueでEnqueued from…の内容も見られますね。(lldb) h th b Show thread call stacks. Defaults to the current thread, thread indexes can be specified as arguments. Use the thread-index "all" to see all threads. Use the thread-index "unique" to see threads grouped by unique call stacks. Syntax: Command Options Usage: thread backtrace [-c <count>] [-s <frame-index>] [-e <boolean>] -c <count> ( --count <count> ) How many frames to display (-1 for all) -e <boolean> ( --extended <boolean> ) Show the extended backtrace, if available -s <frame-index> ( --start <frame-index> ) Frame in which to start the backtrace/usr/lib/system/introspectionを使った機能みたいです。$ ls /usr/lib/system/introspection libdispatch.dylib* libsystem_pthread.dylib* * @discussion * These hooks are only available in the introspection version of the library, * loaded by running a process with the environment variable * DYLD_LIBRARY_PATH=/usr/lib/system/introspectionlldbを直接起動する場合とかは自分で設定する必要があるみたいです。target module list かけてみて libdispatch.dylib が本物っぽいかどうかだけ確認してみますprocess launch -v DYLD_LIBRARY_PATH=/usr/lib/system/introspectionで/usr/lib/system/introspection/libdispatch.dylibをロードしただけでは、thread backtrace -e trueは意図した通りに動きませんでした。 /Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylibってのをlldb-rpc-serverは使ってるけど、lldbで plugin load /Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib してもダメだった。 (edited)process launch -v DYLD_LIBRARY_PATH=/usr/lib/system/introspection -v DYLD_INSERT_LIBRARIES=/Applications/Xcode.app/Contents/Developer/usr/lib/libBacktraceRecording.dylib でイケた。thread backtrace -e true in lldbswift -frontend -replなんてのがあったのね。 $ swift -frontend -repl *** You are running Swift's integrated REPL, *** *** intended for compiler and stdlib *** *** development and testing purposes only. *** *** The full REPL is built as part of LLDB. *** *** Type ':help' for assistance. *** (swift) :help Available commands: :quit - quit the interpreter (you can also use :exit or Control+D or exit(0)) :autoindent (on|off) - turn on/off automatic indentation of bracketed lines :constraints debug (on|off) - turn on/off the debug output for the constraint-based type checker :dump_ir - dump the LLVM IR generated by the REPL :dump_ast - dump the AST representation of the REPL input :dump_decl <name> - dump the AST representation of the named declarations :dump_source - dump the user input (ignoring lines with errors) :print_decl <name> - print the AST representation of the named declarations :print_module <name> - print the decls in the given module, but not submodules API documentation etc. will be here eventually. (swift) $ swift のときに突入するのがそれだと思ってました (edited)lldbを使わないので、--privileged無しのdockerでも使える。--privileged無しdockerなので、Herokuで動いてるSwiftボットでも、修正すれば使える様になりそう。swift -deprecated-integrated-repl がそれですね。[omochi@omochi-iMac-PC43 bne-loci (master *+=)]$ swift -deprecated-integrated-repl *** You are running Swift's integrated REPL, *** *** intended for compiler and stdlib *** *** development and testing purposes only. *** *** The full REPL is built as part of LLDB. *** *** Type ':help' for assistance. *** (swift) ^D [omochi@omochi-iMac-PC43 bne-loci (master *+=)]$ swift Welcome to Apple Swift version 4.2 (swiftlang-1000.0.36 clang-1000.0.4). Type :help for assistance. 1> ^D [omochi@omochi-iMac-PC43 bne-loci (master *+=)]$ swift -frontend -repl *** You are running Swift's integrated REPL, *** *** intended for compiler and stdlib *** *** development and testing purposes only. *** *** The full REPL is built as part of LLDB. *** *** Type ':help' for assistance. *** (swift) ^D-frontend -repl のほうが -deprecated-integrated-repl か・・・print_declとprint_moduleくらいだけど、どれも出力が大きくなるからボットで使えてもありがたみが薄いかな?:print_decl Equatableprotocol Equatable { static func == (lhs: Self, rhs: Self) -> Bool } extension Equatable { @inlinable static func != (lhs: Self, rhs: Self) -> Bool }-frontend -replサポート出来た。swift-DEVELOPMENT-SNAPSHOT-2018-08-26-a があるけど https://github.com/apple/swift/tags にタグが無いな。gitで見ても無さげ。T: Hoge みたいに書けるけど、handle 書くの、気持ち悪い気がしたけど defer 的な気持ちで見れば良いのか。do/catch で囲まなくてよいのでネストが深くならないのが良い?finally を採用せずに defer にしたんだったら、この handle みたいなのの方が理に適ってる気がするけどどうだろう? (edited)handle とスコープについては、 Go の defer はスコープ関係なく関数単位だったはずだから、 handle はどうなんだろう?とさっきから思ってる。StringからNSStringへの暗黙変換が起きる条件って何だろう?NSString.character(at:)は、Linuxでは4.2から起きる。 @swift-4.0.3 @swift-4.1.3 @swift-4.2.4 -frontend -repl import Foundation "test".character(at: 0) (edited)<REPL Input>:1:1: error: value of type 'String' has no member 'character' "test".character(at: 0) ^~~~~~ ~~~~~~~~~ Swift.String:42:16: note: did you mean 'characters'? public var characters: String.CharacterView { get set } ^ (edited)<REPL Input>:1:1: error: value of type 'String' has no member 'character' "test".character(at: 0) ^~~~~~ ~~~~~~~~~ Swift.String:10:16: note: did you mean 'characters'? public var characters: String.CharacterView { get set } ^ Swift.String:8:16: note: did you mean '_characters'? public var _characters: String._CharacterView { get set } ^ (edited)$ echo 'import Foundation; "test".character(at: 0)'|swift -frontend -repl -sdk `xcrun --sdk macosx --show-sdk-path` <REPL Input>:1:20: error: value of type 'String' has no member 'character' import Foundation; "test".character(at: 0) ^~~~~~ ~~~~~~~~~ Swift.String:10:16: note: did you mean 'characters'? public var characters: String.CharacterView { get set } ^ Swift.String:8:16: note: did you mean '_characters'? public var _characters: String._CharacterView { get set } ^Swift.String であり、2) Swift.String が _ObjectiveCBridgeable であり、 3) lookupするメンバー名が Swift.String に生えておらず、 4) ブリッジ先タイプにはそのメンバーが存在し 5) 存在するモジュールが Clang モジュールの Foundation 以外のとき。 っていう条件なので、 corelibs-foundation は 5 の条件をすり抜けて見えちゃっている感じっぽいですね。 (edited)NSStringにインスタンスメンバーを追加すると、Stringからも使えてしまうと。 @swift-4.0.3 @swift-4.1.3 @swift-4.2.4 -frontend -repl import Foundation extension NSString { func hoge() -> String { return "hoge" } } "test".hoge()// r0 : String = "hoge"<REPL Input>:1:1: error: value of type 'String' has no member 'hoge' "test".hoge() ^~~~~~ ~~~~<REPL Input>:1:1: error: value of type 'String' has no member 'hoge' "test".hoge() ^~~~~~ ~~~~.swiftmodule ファイルとしてキャッシュされないですか?.swiftmodule は依存の解決には使われていなかったと思うのですが、記憶違いかも。 (edited).swiftmodule は出力されるものではありますが、他ファイルのコンパイル時に参照されて使われる物ではないですね。A.swift,B.swift, C.swiftあったときにクリーンビルドだと swift -frontend -c -primary-file A.swift B.swift C.swift swift -frontend -c A.swift -primary-file B.swift C.swift swift -frontend -c A.swift B.swift -primary-file C.swift の 3 フロントエンド実行されて、frontend に -primary-file じゃないファイルの .swiftmodule があったらそれに読み替えるみたいな機能はないので。${PROJECT_TEMP_ROOT}/XCBuildData/*-manifest.xcbuild に生成します。 それらをSwiftPMの.build/debug.yamlとかと比較すると違いを調べやすいかも? (edited)$ cat A.swift @available(*, introduced: 1) public func funcA() { print("funcA") } $ cat B.swift public func funcB() { print("funcB") funcA() } $ cat C.swift public func funcC() { print("funcC") } $ cat output.json { "A.swift": { "object": "Derived/A.o", "swiftmodule": "Derived/A~partial.swiftmodule", "swift-dependencies": "Derived/A.swiftdeps", }, "B.swift": { "object": "Derived/B.o", "swiftmodule": "Derived/B~partial.swiftmodule", "swift-dependencies": "Derived/B.swiftdeps", }, "C.swift": { "object": "Derived/C.o", "swiftmodule": "Derived/C~partial.swiftmodule", "swift-dependencies": "Derived/C.swiftdeps", }, "": { "swift-dependencies": "Derived/buildrecord.swiftdeps" } } $ mkdir -p Derived な状態から、 $ xcrun swiftc -v -incremental -output-file-map output.json A.swift B.swift C.swift -module-name MyModule -emit-library -emit-module -o Derived/MyModule.dylib でとりあえずクリーンビルドして、Derived ディレクトリの中身見たり、A.swiftの@available消して同コマンド実行して何が起こってるか確認したりすると面白いです。 (edited)swiftc コマンドに -enable-batch-mode 追加してあげるとXcode10の挙動と同等に。 (edited)[swift 4.2] みたいなバッジがついてたりしたら、安心です
あと、プロジェクトの中で、あるモジュールは4.1、あるモジュールは4.2でビルドしてからリンクします、 みたいなやつ、動くのかもしれないけど信用ならないから心配。 むむ、これって何かトラブルの事例ってあるのですか?SWIFT_VERSION = 4.2になっててもswiftcへは-swift-version 4って渡すのかな?project.pbxprojでSWIFT_VERSION = 4.2になってても過去のXcodeでビルド出来るなら、SWIFT_VERSION = 4.2にしてしまっても良い様な気がしてきた。project.pbxprojでSWIFT_VERSION = 4.2になってても、Xcode 9.0.1, 9.1, 9.2, 9.3.1, 9.4.1はswiftcへ-swift-version 4を渡すのを確認した。SWIFT_VERSION = 4.2にしてもbreaking changeにならないとしても、podspecのswift_versionはどうなんだろう?(indirect.storage -> some -> value)Found 2 object leaking children[0].viewModel: SomeViewModel children[0].textField: UITextFieldSummary: Found 2 leak objects Leaked objects: 0: Description: Node Type: Any Location: .linkedNodes[0] 1: Description: Node Type: Any Location: (root) Circular reference paths: 0: .linkedNodes[0].linkedNodes[0]Sequence ( Collection ?)を型パラメータにとるのがおもしろいですね。 https://github.com/pointfreeco/swift-nonempty (edited)Collection っぽいですね。 https://github.com/pointfreeco/swift-nonempty/blob/master/Sources/NonEmpty/NonEmpty.swift#L1Image<Element>: Sequence を作ってますが Image to Image の map ができてるので。 Sequence 由来のと曖昧になりそうな気がするんですが、 Image to Image の方が優先されてますね。Sequence に map とかついてるのほんと微妙ですよねぇ。 makeIterator だけの純粋な Sequence と map とかを分離してほしい・・・。Collection として扱われるので Collection の map が呼ばれるんじゃないですか?↓とかですよね? public func map<T>(_ transform: (Element) throws -> T) rethrows -> NonEmpty<[T]> { return try NonEmpty<[T]>(transform(self.head), self.tail.map(transform)) }
[Element] を [T] に変換するんで Self じゃなくて、 higher-kinded type がないとできないんですよねぇ・・・。
NonEmpty<Element, NonEmpty<Element, C>>NonEmpty<Element, NonEmpty<Element, C>> は考えてませんでしたが(それぞれの struct を実装するイメージしてました)、多分うまくいきそうな気がします。その場合だけ init(Element, Element, C) を extension で生やせると便利そうですね〜。typealias ArrayLongerThan2<Element> = PrefixedArray<Element, PrefixedArray<Element, PrefixedArrayEnd<Element>>> となっていて、これで flatMap とかの実装が衝突して死んだみたいなエラーに出くわして、ウワァ、ダメなのかみたいに引き返したんです (edited)protocol NonEmptySequence: Sequence { var first: Element { get } } struct NonEmptyArray<Element>: NonEmptySequence { private var array: [Element] init(_ array: [Element]) { precondition(!array.isEmpty) self.array = array } var first: Element { return array[0] } func makeIterator() -> Array<Element>.Iterator { return array.makeIterator() } } (edited)protocol NonEmptySequence: Sequence { var first: Element { get } } struct NonEmptyArray<Element>: NonEmptySequence { private var array: [Element] init(_ array: [Element]) { precondition(!array.isEmpty) self.array = array } var first: Element { return array[0] } func makeIterator() -> Array<Element>.Iterator { return array.makeIterator() } } (edited)protocol NonEmptySequence: Sequence { var first: Element { get } } struct NonEmptyArray<Element>: NonEmptySequence { private var array: [Element] init(_ array: [Element]) { precondition(!array.isEmpty) self.array = array } var first: Element { return array[0] } func makeIterator() -> Array<Element>.Iterator { return array.makeIterator() } }first は Sequence じゃなくて Collection なのか。extension でも生えてないんですね。 map とかは生えてるのに・・・。protocol I { init() } protocol P { associatedtype A: I } extension P { var bar: A? { return nil } } protocol Q: P {} extension Q { var bar: A { return A() } } struct S<T: I>: Q { typealias A = T let value: T var bar: T { return value } } extension Int: I { init() { self = 0 } } let s = S(value: 42) print(s.bar) (edited)safeFirst って何ができなかったんですか? Optional を非 Optional で満たすことができなかったとかではなく??protocol P { associatedtype A var a: A? { get } } struct S<T>: P { typealias A = T let value: T var a: T { return value } } let s = S(value: 42) print(s.a)<stdin>:7:8: error: type 'S<T>' does not conform to protocol 'P' struct S<T>: P { ^ <stdin>:10:9: note: candidate has non-matching type 'T' var a: T { return value } ^ <stdin>:4:9: note: protocol requires property 'a' with type 'S<T>.A?'; do you want to add a stub? var a: A? { get } ^1. オブジェクトを全部スキャンする 2. 検査したい関数を実行する 3. スキャンしてあるweak参照の先に生きてるオブジェクトが無いことを確認する (edited)let target = createSomething() let memoryLeaks = detectLeaks(target) XCTAssertTrue( memoryLeaks.leakedObjects.isEmpty, memoryLeaks.prettyDescription )class Cat { var parent: Cat? } func createSomething() -> Cat { let cat1 = Cat() let cat2 = Cat() let cat3 = Cat() cat2.parent = cat3 cat3.parent = cat2 return cat1 }Summary: Found 0 leaked objects Leaked objects: (empty)class Cat { var parent: Cat? var child: Cat? } func createSomething() -> Cat { let cat1 = Cat() let cat2 = Cat() let cat3 = Cat() cat2.parent = cat3 cat3.parent = cat2 cat2.child = cat1 return cat1 }let json = """ [{ "id": 0, "mode": "high" },{ "id": 1, "mode": "middle" },{ "id": 2, "mode": "moddle" },{ "id": 3, "mode": "low" }] """ enum Mode: String, Decodable { case high case middle case low } struct Object: Decodable { let id: Int let mode: Mode } let objects = try! JSONDecoder().decode([Object].self, from: json.data(using: .utf8)!) print(objects) ↑のような時に、Jsonのデコードを失敗とせずid:0,1,3のObjectの配列を返すような実装がしたい場合Arrayのラッパーみたいなものを書く感じになるのでしょうか?enum Mode: String, Decodable { case high case middle case low } struct Object: Decodable { let id: Int let mode: Mode? } do { let decoder = JSONDecoder() let data = json.data(using: .utf8)! let objects = try decoder.decode([Object].self, from: data).compactMap({ $0.mode != nil }) print(objects) } catch { print(error) }import Foundation let json = """ [{ "id": 0, "mode": "high" },{ "id": 1, "mode": "middle" },{ "id": 2, "mode": "moddle" },{ "id": 3, "mode": "low" }] """ enum Mode: String, Decodable { case high case middle case low } struct Object: Decodable { let id: Int let mode: Mode? enum CodingKeys: CodingKey { case id, mode } init(from decoder: Decoder) throws { let container = try decoder.container(keyedBy: CodingKeys.self) self.id = try container.decode(Int.self, forKey: .id) self.mode = try? container.decode(Mode.self, forKey: .mode) } } let objects = try! JSONDecoder().decode([Object].self, from: json.data(using: .utf8)!).filter { $0.mode != nil } print(objects)[main.Object(id: 0, mode: Optional(main.Mode.high)), main.Object(id: 1, mode: Optional(main.Mode.middle)), main.Object(id: 3, mode: Optional(main.Mode.low))]import Foundation let json = """ [{ "id": 0, "mode": "high" }, { "id": 1, "mode": "middle" }, { "id": 2, "mode": "moddle" }, { "id": 3, "mode": "low" } ] """ enum Mode: String, Decodable { case high case middle case low } struct Object: Decodable { let id: Int let mode: Mode init(id: Int, mode: Mode) { self.id = id self.mode = mode } } struct FailableBox<T> : Decodable where T : Decodable { init(from decoder: Decoder) throws { self.value = try? T.init(from: decoder) } var value: T? } let objects: [Object] = try! JSONDecoder() .decode([FailableBox<Object>].self, from: json.data(using: .utf8)!) .compactMap { $0.value } print(objects)[main.Object(id: 0, mode: main.Mode.high), main.Object(id: 1, mode: main.Mode.middle), main.Object(id: 3, mode: main.Mode.low)]import Foundation enum Result { case win case lose case none } var results: [Int : Result] = [:] results[0] = .win results[1] = .lose results[2] = .none if results[2] == nil { print("result.2 is nil") }result.2 is nilimport Foundation enum Result { case win case lose case none } var results: [Int : Result] = [:] results[0] = .win results[1] = .lose results[2] = .some(.none) if results[2] == nil { print("result.2 is nil") }Dictionary の subscript が -> Value? だからかぁ。get と set で、 get は Optional だけど set は Optional でなくしたいケース、ときどきある気がしてる。enum Result { case win case lose case none } func foo(_ resultOrNil: Result?) { print(resultOrNil as Any) } foo(.win) foo(.lose) foo(.none) foo(Result.none)Optional(main.Result.win) Optional(main.Result.lose) nil Optional(main.Result.none)none は避けるようにした方が無難そうですね。 (edited)removeValue(forKey:) だけにして、 subscript set を非 Optional にしてほしいです・・・。set で非 Optional 化できるようになっても、互換性の問題で Dictionary の subscript set をなくすのってできないかもですねdict[key] = nil って便利構文なんじゃなくて、 subscript の仕様制約上 set を非 Optional にできなかったため仕方なくついてるものだと思ってました。 (edited)nilリテラルの代入で削除以外が起こることはないはずだから、nilリテラルの代入以外のOptionalの代入をコンパイラか別のLinterが警告する というのが妥当か。print のOptional 警告はあるから、 Dictionary の subscript set でもその線が妥当そうですね。Optional(2018)年 問題回避に役立ちますけど。CustomStringConvertible 以外できなくしちゃってもいいと思うんですよね。@nilWarning 属性みたいなものをつけられるといいのか?Optional 暗黙変換問題はどこででも起こりうるので、そういうのがあると良いのかも?@discardableResult とかと同じで Attribute 付けるとかしないとできなくないですか?enum Result { case win case lose case none } let result: Result? = .none これは暗黙変換ではなく Optional<Result>.none を入れてるだけですよね。// result : Result? = nilimport Foundation enum Computer { case win case mac } enum Result { case win case lose case none case some(Computer) } func foo(_ resultOrNil: Result?) { print(resultOrNil as Any) } foo(.win) foo(.lose) foo(.none) foo(.some(.win)) print("") foo(Result.some(.win))Optional(main.Result.win) Optional(main.Result.lose) nil Optional(main.Result.win) Optional(main.Result.some(main.Computer.win))enum Hoge { case waiwai case mu(Never) } let hoge = Hoge.waiwai switch hoge { case .waiwai: print("わいわい") }Result<Foo, Never> の switch で case .failure 書かなくても網羅的になるはず。 https://discordapp.com/channels/291054398077927425/291054454793306112/336463567039496192 "([0-9a-fA-F]+)\\.\\.([0-9a-fA-F]+);([a-zA-Z]+)" そうですねえ。i と element の片方を let 、片方を var にする方法ってありますか? let array = [2, 3, 5] for var (i, element) in array.enumerated() { print("\(i): \(element)") }let array = [2, 3, 5] for (i, var element) in array.enumerated() { element += 1 print("\(i): \(element)") }0: 3 1: 4 2: 6let array = [2, 3, 5] for (i, var element) in array.enumerated() { i += 1 element += 1 print("\(i): \(element)") }<stdin>:4:6: error: left side of mutating operator isn't mutable: 'i' is a 'let' constant i += 1 ~ ^var(let a, var b) = (2, 3)var (x, y) = (0, 0) y = 190 print(x, y) この形だとx is never mutatedの警告すら出ないですねvar にするのがいいのかな。let x: Int var y: Int (x, y) = (0, 0) 一応これは可能です。 let point: (Int, Int)? = nil if case (let x, var y)? = point { print(x, y) }static subscript って作れないのか。 @swift-4.2.4
struct S { static subscript(i: Int) -> Int { return i + 1 } }<stdin>:3:12: error: subscript cannot be marked 'static' static subscript(i: Int) -> Int { return i + 1 } ~~~~~~~^ class Container<Content> { init(a: Content) { // イニシャライザA fatalError() } init<T>(b: T) where T == Content { // イニシャライザB self.init(a: b as! Int) } } (edited)class Container<Content> { init(a: Content) { fatalError() } init<T>(b: T) where T == Content { self.init(a: b as! Int) } }<stdin>:7:27: error: same-type requirement makes generic parameters 'T' and 'Content' equivalent init<T>(b: T) where T == Content { ^ #0 0x000000000410ac94 PrintStackTraceSignalHandler(void*) (/usr/bin/swift+0x410ac94) #1 0x0000000004108b22 llvm::sys::RunSignalHandlers() (/usr/bin/swift+0x4108b22) #2 0x000000000410ae42 SignalHandler(int) (/usr/bin/swift+0x410ae42) #3 0x00007fdc32623390 __restore_rt (/lib/x86_64-linux-gnu/libpthread.so.0+0x11390) #4 0x00000000016b1b09 swift::FunctionType::get(swift::Type, swift::Type, swift::AnyFunctionType::ExtInfo const&) (/usr/bin/swift+0x16b1b09) #5 0x00000000017fde74 swift::GenericFunctionType::substGenericArgs(swift::SubstitutionMap const&) (/usr/bin/swift+0x17fde74) #6 0x00000000017fdd02 swift::GenericFunctionType::substGenericArgs(llvm::ArrayRef<swift::Substitution>) (/usr/bin/swift+0x17fdd02) #7 0x000000000147abe0 swift::UncurriedCandidate::UncurriedCandidate(swift::ValueDecl*, unsigned int) (/usr/bin/swift+0x147abe0) #8 0x000000000147f346 swift::CalleeCandidateInfo::CalleeCandidateInfo(swift::Type, llvm::ArrayRef<swift::constraints::OverloadChoice>, bool, swift::constraints::ConstraintSystem&, bool) (/usr/bin/swift+0x147f346) #9 0x0000000001466f19 (anonymous namespace)::FailureDiagnosis::visitApplyExpr(swift::ApplyExpr*) (/usr/bin/swift+0x1466f19) #10 0x000000000144d4d6 swift::ASTVisitor<(anonymous namespace)::FailureDiagnosis, bool, void, void, void, void, void>::visit(swift::Expr*) (/usr/bin/swift+0x144d4d6) #11 0x0000000001446642 swift::constraints::ConstraintSystem::diagnoseFailureForExpr(swift::Expr*) (/usr/bin/swift+0x1446642) #12 0x000000000144cb76 swift::constraints::ConstraintSystem::salvage(llvm::SmallVectorImpl<swift::constraints::Solution>&, swift::Expr*) (/usr/bin/swift+0x144cb76) #13 0x0000000001352138 swift::TypeChecker::solveForExpression(swift::Expr*&, swift::DeclContext*, swift::Type, swift::FreeTypeVariableBinding, swift::ExprTypeCheckListenwhere T == Content はダメだよって正しいエラーを吐いたあとにセグフォで死ぬのを見つけたT しか受けないことが決まっているイニシャライザAに T ではない Int を渡せちゃってる?Stack dump: 0. Program arguments: /Applications/Xcode_10_1.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swift -frontend -interpret Development/MyPlayground.playground/Contents.swift -enable-objc-interop -sdk /Applications/Xcode_10_1.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.14.sdk -color-diagnostics -module-name Contents 1. While type-checking 'init(b:)' at Development/MyPlayground.playground/Contents.swift:6:5 2. While type-checking statement at [Development/MyPlayground.playground/Contents.swift:6:38 - line:8:5] RangeText="{ self.init(a: b as! Int) }" 3. While type-checking expression at [Development/MyPlayground.playground/Contents.swift:7:9 - line:7:31] RangeText="self.init(a: b as! Int)" fish: 'swift Development/MyPlayground.…' terminated by signal SIGSEGV (Address boundary error)class Container<Content> { init(a: Content) { fatalError() } init<T>(b: T) where T == Content { self.init(a: b as! Int) } }<stdin>:7:27: error: same-type requirement makes generic parameters 'T' and 'Content' equivalent init<T>(b: T) where T == Content { ^ <stdin>:8:14: error: cannot invoke 'Container<Content>.init' with an argument list of type '(a: Int)' self.init(a: b as! Int) ^ <stdin>:8:14: note: expected an argument list of type '(a: Content)' self.init(a: b as! Int) ^ <stdin>:7:5: error: designated initializer for 'Container<Content>' cannot delegate (with 'self.init'); did you mean this to be a convenience initializer? init<T>(b: T) where T == Content { ^ convenience <stdin>:8:14: note: delegation occurs here self.init(a: b as! Int) ^for i in 1... { print(i) } これ無限ループになるんですね、終端値無くてもrangeになるんだfunc eatBuffer() { self.buffer = Array(self.buffer[self.pos...]) self.pos = 0 } ↑ストリーム処理を書いているときにこれをよくやりますzip(0..., arraySlice)swiftcの代わりにSourceKitを使うSwiftSyntaxだ。swiftc -> JSON -> SwiftSyntax -> SwiftLintFramework が SourceKit -> JSON -> SwiftSyntax -> SwiftLintFramework になってる。 (edited)[String: Any]ベースよりも速くなる可能性があるな。 https://github.com/apple/swift-syntax/blob/master/Sources/SwiftSyntax/ByteTreeDeserialization.swiftPackage.resolvedをコミットしていないリポジトリにいつの間にかPackage.resolvedが生成されたり、知らないうちにPackage.resolvedが更新されたりしてたりしたのが不思議だったのだけど、SourceKit-LSPを入れたVSCodeでワーキングコピーを開いてたからだった。Package.swiftの中身がLinux向けとmacOS向けで依存するライブラリが違ってて、リポジトリにはLinux向けに生成されたPackage.resolvedがコミットされてて、それをmacOSのVSCodeで開くとPackage.resolvedが更新される。swift-5.0-DEVELOPMENT-SNAPSHOT-…のmacOS版でStringのUTF16関連がぶっ壊れてるぽい。Data.withUnsafeBytes(_:)がクロージャへコピーされた一時メモリを指すポインタを渡すように変わったからだった。import Foundation let data = "test".data(using: .utf8)! dump(data) data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) -> Void in dump(bytes) } (edited)▿ 4 bytes - count: 4 ▿ pointer: 0x00000000079af0d0 - pointerValue: 127594704 ▿ bytes: 4 elements - 116 - 101 - 115 - 116 ▿ 0x00000000079af0d0 - pointerValue: 127594704 (edited)pointerValueが違う。 $ xcrun --toolchain org.swift.5020181225a swift swift_oss_helper command enabled. Welcome to Apple Swift version 5.0-dev (LLVM c351ac7354, Clang aadec4ff83, Swift 5cfc2e7ba9). Type :help for assistance. 1> import Foundation 2. let data = "test".data(using: .utf8)! 3. dump(data) 4. data.withUnsafeBytes { (bytes: UnsafePointer<UInt8>) in 5. dump(bytes) 6. } ▿ 4 bytes - count: 4 ▿ pointer: 0x00007ffeefbff818 - pointerValue: 140732920756248 ▿ bytes: 4 elements - 116 - 101 - 115 - 116 ▿ 0x00007ffeefbffb30 - pointerValue: 140732920757040 (edited)Codableは便利ですが、FoundationのJSONEncoder, JSONDecoderを使っていて微妙に不便に感じる事があります。自分がいろいろな案件をこなしたり、他人の困り事を聞いてきた上で、...LinkedListObject周りリークしまくりでは。LinkedListObject.IndexをLinkedListObject.Node?にしたらシンプルになるのでは?と試してたのだけど、public typealias Index = Optional<Node>を定義してもCollectionにconform出来ていないと文句を言ってくる。Collection.IndexにはOptionalを使えないのかな。extension Optional: Comparable where Wrapped: Comparableになってなかった。NodeをSequenceにすると、func <が少し簡単になる。nextをfollowingに変えてる。 public static func < (lhs: LinkedListObject.Node, rhs: LinkedListObject.Node) -> Bool { if lhs == rhs || lhs.previous == rhs { return false } for following in lhs where following == rhs { return true } return false }public typealias Index = Node?案はやはり却下という結論に至った。func copyでoldIndicesに書き戻してるところは、何に使うつもりで書かれてたのですか?NodeをCollectionに。 extension LinkedListObject.Node: Collection { public enum Index: Comparable { case node(LinkedListObject.Node), none public static func < (lhs: Index, rhs: Index) -> Bool { switch (lhs, rhs) { case (.node(let lhs), .node(let rhs)): return lhs < rhs case (.node(_), .none): return true default: return false } } init(_ node: LinkedListObject.Node?) { self = node.map(Index.node) ?? .none } var node: LinkedListObject.Node? { guard case .node(let node) = self else { return nil } return node } } public var startIndex: Index { return .node(self) } public var endIndex: Index { return .none } public subscript(position: Index) -> LinkedListObject.Node { guard let node = position.node else { preconditionFailure("Index out of range") } return node } public func index(after i: Index) -> Index { guard let node = i.node, let nextIndex = node.next.map(Index.node) else { return .none } return nextIndex } }LinkedListObject.Node.IndexをLinkedListObject.Indexに。BidirectionalCollectionはLinkedListObjectで対応ですね。 extension LinkedListObject : BidirectionalCollection { public func index(before i: Index) -> Index { checkValidIndex(i) if i == endIndex { return Index(last) } precondition(i != startIndex, "Can't advance before startIndex") return Index(i.node?.previous) } }NodeがCollectionになれるだけで、Collectionであるメリットは全く無い。Sequenceで十分。copy周りはRangeReplaceableCollectionのreplaceSubrange()みたいに、操作に必要なデータも渡してしまう方が良い気がする。XCTAssertNoThrow の引数にtestBookModelに相当するクロージャー渡すのでもダメなのかな?(試してない)#define で定義された式展開マクロみたいですね、これはどうしようもない。XCTAssertNoThrow(try { let book = try BookModel(from: sampleDictionary) XCTAssertEqual(book.name, "...") XCTAssertEqual(book.description, "...") }())import XCTest :print_decl XCTAssertNoThrowfunc XCTAssertNoThrow<T>(_ expression: @autoclosure () throws -> T, _ message: @autoclosure () -> String = default, file: StaticString = #file, line: UInt = #line)XCTAssertNoThrowのオリジナルはマクロの集合体で、シンボルとしては存在しないから、同じものとして扱っていないのでは。 #define XCTAssertNoThrow(expression, ...) \ _XCTPrimitiveAssertNoThrow(self, expression, @#expression, __VA_ARGS__) #define _XCTPrimitiveAssertNoThrow(test, expression, expressionStr, ...) \ ({ \ @try { \ (void)(expression); \ } \ @catch (NSException *exception) { \ _XCTRegisterFailure(test, _XCTFailureDescription(_XCTAssertion_NoThrow, 0, expressionStr, [exception reason]), __VA_ARGS__); \ } \ @catch (...) { \ _XCTRegisterFailure(test, _XCTFailureDescription(_XCTAssertion_NoThrow, 1, expressionStr), __VA_ARGS__); \ } \ }) …var errorDescription: String? を実装してやれば、NSError変換されるときに勝手にlocalizedDescriptionになった。_swift_Foundation_getErrorDefaultUserInfo これですかねCustomStringConvertibleで良さげ。 @swift-4.0.3
import XCTest struct MyError: Error, CustomStringConvertible { var description = "my error" } class Test: XCTestCase { func testA() throws { throw MyError() } static var allTests = [("testA", testA)] } XCTMain([testCase(Test.allTests)])Test Suite 'All tests' started at 2019-01-21 20:10:23.991 Test Suite 'bin.xctest' started at 2019-01-21 20:10:23.993 Test Suite 'Test' started at 2019-01-21 20:10:23.993 Test Case 'Test.testA' started at 2019-01-21 20:10:23.993 <EXPR>:0: error: Test.testA : threw error "my error" Test Case 'Test.testA' failed (0.004 seconds) Test Suite 'Test' failed at 2019-01-21 20:10:23.997 Executed 1 test, with 1 failure (1 unexpected) in 0.004 (0.004) seconds Test Suite 'bin.xctest' failed at 2019-01-21 20:10:23.997 Executed 1 test, with 1 failure (1 unexpected) in 0.004 (0.004) seconds Test Suite 'All tests' failed at 2019-01-21 20:10:23.997 Executed 1 test, with 1 failure (1 unexpected) in 0.004 (0.004) seconds== で書いた場合だけか?// : Same-type constraint type 'P' does not conform to required protocol 'P' extension P where Self == P { func b() {} }protocol P { func a() } struct ExP : P { let p: P func a() { print("existential") } } class Actor<T: P> { let p: T init(_ p: P) { self.p = ExP(p: p) } init(_ p: T) { self.p = p } }SWIFT_EXECを置き換えて起動するのは面白い。 https://swift.org/blog/sourcekitd-stress-tester/swift-DEVELOPMENT-SNAPSHOT-2019-02-26-a.xctoolchain
.package(url: "https://github.com/apple/swift-syntax.git", .branch("master")), の環境でやっているんですけど、SwiftSyntaxのビルドでSyntaxKindなどがないと怒られてしまいます。Replace <#Specify Release tag#> by the version of SwiftSyntax that you want to use (see the following table for mapping details). Swift Release Tag SwiftSyntax Release Tag swift-4.2-RELEASE 0.40200.047326318ってSwift 4.2の変更だよね。 https://developer.apple.com/documentation/xcode_release_notes/xcode_10_2_beta_4_release_notes/swift_5_release_notes_for_xcode_10_2_beta_4
@swift-4.1.3 @swift-4.2.4 @swift-5.0.3
func forceCast<U>(_ value: Any?, to type: U.Type) -> U { return value as! U } let value: Any? = 42 print(forceCast(value, to: Any.self)) // Prints "Optional(42)" // (Prior to Swift 5, this would print "42".) print(value as! Any) // Prints "Optional(42)"Optional(42) Optional(42)stderr:<stdin>:10:13: warning: forced cast from 'Any?' to 'Any' always succeeds; did you mean to use 'as'? print(value as! Any) ^~~ as42 Optional(42)stderr:<stdin>:10:13: warning: forced cast from 'Any?' to 'Any' always succeeds; did you mean to use 'as'? print(value as! Any) ^~~ asOptional(42) Optional(42)stderr:<stdin>:10:13: warning: forced cast from 'Any?' to 'Any' always succeeds; did you mean to use 'as'? print(value as! Any) ^~~ asstruct Outer { typealias E = NestedValidation.T protocol NestedValidation { typealias T = A.B } }func foo<Value>(_ x: Any?, as type: Value.Type) -> Value? { return x as? Value } dump(foo(nil, as: Any.self))
-swift-version 5以外だと、Swift 4.1の挙動に戻るらしい… (edited)-swift-version 4.2を付けることでSwift 4.2と非互換になるって、意味がわからん。#if compilerでは区別できそう? (edited)makefile内で、xcodebuildのバージョンによりswift buildへ渡す-Xswiftc -static-stdlibの有無を使い分ける必要があるぽい。class A {} struct Box<T: A> {} let box = Box() print(box)users.map(\.email)// `self` key paths [1, nil, 3, nil, 5].compactMap(\.self) ↑これオシャレでいいな。 { $0 } の意味。boolObservable.filter { $0 }も同様に書ける?func foo<T>(_ t: T) { print(t) } let a: Any = 42 foo(a)func foo<T: Any>(_ t: T) { print(t) } let a: Any = 42 foo(a)func foo<T: AnyObject>(_ t: T) { print(t) } class C {} let a: AnyObject = C() foo(a)func foo<T: Error>(_ t: T) { print(t) } struct E: Error {} let a: Error = E() foo(a)<stdin>:8:1: error: cannot invoke 'foo' with an argument list of type '(Error)' foo(a) ^ <stdin>:8:1: note: expected an argument list of type '(T)' foo(a) ^func foo<T: Error>(_ t: T) { print(t) } struct E: Error {} let a: Error = E() foo(a)if #available の否定ほしい const result = require('child_process').execSync('docker images kishikawakatsumi/swift --format "{{.Tag}}"').toString();ほとんどの Container Registry ストレージ バケットに使用されるデフォルトの Cloud Storage クラスは、Multi-Regional です。 Multi-Regional バケットの月額料金は、約 $0.026/GB です。
https://cloud.google.com/container-registry/pricingstruct Stone { var a: Int var b: Int init(a: Int = 10 * 2 + 3 /*草*/ - (5 + 2), b: Int = 20) { self.a = a self.b = b } }// SIL struct Stone { @_hasStorage var a: Int { get set } @_hasStorage var b: Int { get set } init(a: Int = 10 * 2 + 3 /*草*/ - (5 + 2), b: Int = 20) }func nthOfEach( _ n: Int, from heterogeneousCollections: [any Collection] ) -> Any { return heterogeneousCollections.map { collection in // collection is `any Collection` let nthIndex = collection.startIndex.advanced(by: n) // error: inferred static type of nthIndex is something like `any Collection.Index`, // so compiler can’t guarantee it indexes `collection` … correct? return collection[nthIndex] } }
https://forums.swift.org/t/se-0244-opaque-result-types-reopened/22942/49func main() { let ac = AnyCollection<Int>([1]) let s = AnyCollection<Character>("str") let x = ac[s.startIndex] // Fatal error: Index type mismatch! } main()let ac = AnyCollection<Int>([1]) let x = ac[ac.startIndex]AnyCollection を使った場合に↑の二つのコードを区別してコンパイル時の挙動を変える話。AnyCollection というか generalized existential の問題の話で、同じことが type erasure でも言えるということじゃないかな。 (edited)AnyCollection って AnyCollection<Element, Indices> とかの方がよかったのでは・・・。 (edited)Iterator と SubSequence はいいけど、 Indices が定まらないのはいいのかな・・・。 (edited)Self 戻り値はいいけど引数はダメみたいな話?AnyCollection<Element, Indices> にすれば型安全にできる気がするけど、 generalized existential って必ずしもすべての associated type を指定しなければならないわけじゃないから、その辺りの型安全性を解決するのに path-dependent type が必要という話なんじゃないかな? (edited)AnyCollection の場合は Indices を型パラメータにしなかったのでそれを指定する手段がないから実行時エラーにするしかない。func g(_ x: P) { let a = x.value x.value = a }value プロパティについて、コードのフローを考慮して同じ型であることが保証できる場合のみ代入できるようにするとか?
as! 的な。let cs: [Character] = ["a", "b"] let str: String = "cde" func concat<T>(_ a: AnyCollection<T>, _ b: AnyCollection<T>) -> [T] { return a.map { $0 } + b.map { $0 } } let r = concat(AnyCollection(cs), AnyCollection(str)) print(r)["a", "b", "c", "d", "e"]let cs: [Character] = ["a", "b"] let str: String = "cde" func concat<T>(collections: [AnyCollection<T>]) -> [T] { return collections.reduce([]) { $0 + $1.map { $0 } } } let r = concat(collections: [AnyCollection(cs), AnyCollection(str)]) print(r)["a", "b", "c", "d", "e"]func hoge<T>() -> some Collection<.Element == T> とかを許すので (edited)any Colleciton とか any Collection<.Element == Int> とか any Collection<.Element == Int, .Index == Int> (edited)== するときとかはそういうパターン。any Collection<.Element == Int> の場合Index: any Comparable として生成されるのかな、それだと例のクラッシュがありえるけどfunc nthOfEach( _ n: Int, from heterogeneousCollections: [any Collection] ) -> Any { return heterogeneousCollections.map { collection in // collection is `any Collection` let nthIndex = collection.startIndex.advanced(by: n) // error: inferred static type of nthIndex is something like `any Collection.Index`, // so compiler can’t guarantee it indexes `collection` … correct? return collection[nthIndex] } }collection … correct? mutating func Array.clip(low, high)みたいなextensionをはやしてて、数が多くなってきたのでArray.ex.clip(low, high)に移したいなと思ったんですが値型だとこれできないですよね……extension Array { var ex: Ex<Element> { get { return Ex(self) } set { self = newValue.array } } }exをどっかに代入されたときなんですよね。.ex 方式、そもそもあんまりよくない気もするResult は標準ライブラリの型だから、 @inlinable がなくても specialize は行われるっていう認識でいいのかな?それだと "benchmarked to check if it's beneficial and not harmful" を作るのは更に難しそう。 (edited)@inlineable 以前から specialize された件って、 @_inlinable とかのおかげだったってこと?public struct MyStruct1 { public internal(set) var x: Int @inlinable public init(x: Int) { self.x = x } } public struct MyStruct2 { @usableFromInline public internal(set) var x: Int @inlinable public init(x: Int) { self.x = x } }<stdin>:11:5: error: '@usableFromInline' attribute can only be applied to internal declarations, but 'x' is public @usableFromInline ^~~~~~~~~~~~~~~~~ <stdin>:6:9: error: setter for 'x' is internal and cannot be referenced from an '@inlinable' function self.x = x ^ <stdin>:2:30: note: setter for 'x' is not '@usableFromInline' or public public internal(set) var x: Int ^ <stdin>:16:9: error: setter for 'x' is internal and cannot be referenced from an '@inlinable' function self.x = x ^ <stdin>:12:30: note: setter for 'x' is not '@usableFromInline' or public public internal(set) var x: Int ^ func testMultiplyPixel() { var rgba = [Double](repeating: 1, count: 4) let scalar: Double = 0.99 measure { // 0.108sec for _ in 0..<1000000 { rgba.withUnsafeMutableBufferPointer { var p = $0.baseAddress! for _ in 0..<$0.count { p.pointee *= scalar p += 1 } } } } } func testMultiplyPixel3() { var rgb = [Double](repeating: 1, count: 3) let scalar: Double = 0.99 measure { // 0.141sec for _ in 0..<1000000 { rgb.withUnsafeMutableBufferPointer { var p = $0.baseAddress! for _ in 0..<$0.count { p.pointee *= scalar p += 1 } } } } } 要素4つのほうが3つより早いという直感に反する結果に……$swiftc --emit-assembly だけど[araki@Arakis-MBP No Backup]$ diff main3.txt main4.txt 22c22 < movl $3, %ecx --- > movl $4, %ecx[araki@Arakis-MBP No Backup]$ diff main3.txt main4.txt 35c35 < movl $3, %edi --- > movl $4, %edi 37c37 < movq $3, 16(%rax) --- > movq $4, 16(%rax) 40,41c40 < movabsq $4607182418800017408, %rcx < movq %rcx, 48(%rax) --- > movupd %xmm0, 48(%rax)[araki@Arakis-MBP No Backup]$ cat main.swift var rgb = [Double](repeating: 1, count: 3) let scalar: Double = 0.99 rgb.withUnsafeMutableBufferPointer { var p = $0.baseAddress! for _ in 0..<$0.count { p.pointee *= scalar p += 1 } } [araki@Arakis-MBP No Backup]$ swiftc -emit-assembly -O main.swift > main3.txt[araki@Arakis-MBP No Backup]$ diff main3.txt main4.txt 20,23d19 < .section __TEXT,__literal8,8byte_literals < .p2align 3 < LCPI1_2: < .quad 4607092346807469998 43c39 < movl $3, %edi --- > movl $4, %edi 45c41 < movq $3, 16(%rax) --- > movq $4, 16(%rax) 48,49c44 < movabsq $4607182418800017408, %rcx < movq %rcx, 48(%rax) --- > movups %xmm0, 48(%rax) 85c80 < movl $3, %edi --- > movl $4, %edi 89,94c84,90 < movupd 32(%rdi), %xmm0 < mulpd LCPI1_1(%rip), %xmm0 < movupd %xmm0, 32(%rdi) < movsd 48(%rdi), %xmm0 < mulsd LCPI1_2(%rip), %xmm0 < movsd %xmm0, 48(%rdi) --- > movapd LCPI1_1(%rip), %xmm0 > movupd 32(%rdi), %xmm1 > movupd 48(%rdi), %xmm2 > mulpd %xmm0, %xmm1 > movupd %xmm1, 32(%rdi) > mulpd %xmm0, %xmm2 > movupd %xmm2, 48(%rdi)func test() { var rgb = [Double](repeating: 1, count: 4) let scalar: Double = 0.99 rgb.withUnsafeMutableBufferPointer { var p = $0.baseAddress! for _ in 0..<$0.count { p.pointee *= scalar p += 1 } } }rgb[0...1]は128bitリテラル読み書き1回 rgb[2]は64bit即値書き込み1回 - main4: rgb[0...1] [2...3] 128bitリテラル読み込み1回書き込み2回 - 乗算: - main3: rgb[0...1] 128bit対象レジスタへ読み込み1回、128bitリテラルとレジスタの乗算1回、128bit書き込み1回 rgb[2] 64bit対象読レジスタへみ込み1回、64bit64bitリテラルとレジスタの乗算1回、64bit書き込み1回 - main4: rgb[0...1] [2...3] 128bitリテラルをレジスタへ読み込み1回、128bit対象をレジスタへ読み込み2回、128bitレジスタ同士の乗算2回、128bit書き込み2回 (edited)xmm0に書き込まれるから順次実行、main4は乗算の結果を書き込む先がxmm1とxmm2別になってるから並列実行してそう。 (edited)scalar を1度読めば使い回せるけど、 main3の方は 128bit 同士と 64bit同士になる関係で、 scalar の読み込みが多くなっちゃう?async/await が導入されたら [weak self] やりたくなることが多そうだけどどうなるんだろう?↓とか? func asyncFoo() async { weak var welf: ViewController? = self let isFinished = await UIView.animate(withDuration: 0.5, animations: { ... }) guard let self = welf else { return } ... }guard let だと同一スコープで複数回同じ名前付けれないから、これまでネストしてた非同期処理で guard let self = を何度も書けなくて self のシャドーイングに落ち着いた名前問題が再燃する? (edited)await 後は(同一スコープなのに)いきなり明示的 self. が必要になったり、色々変な感じになることがありそう・・・。 (edited)async なクロージャと組み合わせられるとまずそう?class C { let foo: () async -> Void = { [weak self] in guard let self = self else { return } await bar() baz(self) } } (edited)[weak self] 挟むから大丈夫か (edited)let fibs = Generator { yield in var (a, b) = (0, 1) while true { await yield(a) (a, b) = (b, a + b) } }func actInf() { while true { sendMessage() } } ↑もしこれを(別スレッドなどで)呼び出したらselfは永遠に解放されないZ_SYNC_FLUSH = 00 00 FF FF でスプリットしろと書いてあるがこの4バイトが見当たらない。WebSocketClientでWebSocketClientUpgradeHandler がreceivedContentsへchannelReadで受け取ったデータを溜め込む実装は筋が悪いと思うんだよね。 (edited)WebSocketClientUpgradeHandlerのchannelActiveは下流へchannelActiveを発火せず、channelReadで.switchingProtocolsを受け取ったら自身をハンドラから削除してから下流へchannelActiveを発火することで、意図しないchannelReadが発生しない様にしてる。 (edited)channelActiveを受け取らない限りreadもwriteも起きないと思います。WebSocketClientUpgradeHandler のchannelReadはfireChannelReadを呼ばない前提です。channelActive, channelReadを次のハンドラへ流さないことで、次のハンドラからのwriteを抑制して予期しないchannelReadを発生させない」ですね。 (edited)func median<T: Comparable>(bp: UnsafeMutableBufferPointer<T>) -> T { // error: cannot use mutating member on immutable value: 'bp' is a 'let' constant bp.sort() return bp[bp.count / 2] } これってMutableCollectionの定義に従うためだけにmutatingなんですかねstruct である UnsafeMutableBufferPointer の nonmutating func で状態が変更されるってカオスな気も。subscript はすでにそうだった。nonmutatimg func でオーバーライドができればいいのかな?protocol P { mutating func foo() } extension P { mutating func foo() { print("P") } } struct S: P { func foo() { print("S") } } let s: S = S() s.foo() // ↓エラー // let p: P = s // p.foo() var p: P = s p.foo()nonmutating な sort 実装できそうだね。
NSMutableArray とかもなってるかも?Sequence だけど MutableCollection じゃないのか。 > NSMutableArrayUnsafeMutableAudioBufferListPointer - UnsafeMutableBufferPointer - UnsafeMutableRawBufferPointersubscript set が nonmutating であるべきかは判断が難しい・・・。 https://developer.apple.com/documentation/swift/emptycollection/1541374-subscriptsort もいけそうw https://developer.apple.com/documentation/swift/collectionofoneCollectionOfOne については、 sort は nonmutating にできるけど、 subscript set はできないね。CollectionOfOne は微妙だし、 EmptyCollection も意見が分かれるかもだけど、ポインタ系はやるべきな気がするね。 subscript set も nonmutating なわけだし。MutableCollection 以外で Mutable* で nonmutating できそうなものとかあるかなぁ。RangeReplaceableCollection 見てたけど、 append とかはできないよね。count を書き換えないといけないから。append 生えてないのか。let count だけど、一応 self 書き換えはできるだろうけど。append とかもない? (edited)UnsafeMutableAudioBufferListPointer って初めて見た。UnsafeMutableBufferPointer - UnsafeMutableRawBufferPointerprotocol P { mutating func foo() } extension Array: P { func foo() { } } var a = [0, 1, 2] var p: P = a p.foo() こういう形のときCoWがどうなるんだろうとか思ったり。func test1(bp: UnsafeMutableBufferPointer<Double>) { bp[0] = 0 } func test2(slice: Slice<UnsafeMutableBufferPointer<Double>>) { slice[0] = 0 // error: cannot assign through subscript: 'bp' is a 'let' constant } こっちは対処するのめんどくさそうですが……func f() { ここに実装があるよ } mutating func f() { f() } // プロトコルへのconformだよ これが出来れば丸く解決する (edited)inout の話、前に話したことあるよね。 withUnsafeMutableBufferPointer の inout は過剰だけど、現状表現できるものが inout しかないって。nonmutating で実装されれば問題ない?self 書き換えならぬ inout で渡されたもの自体を書き換えることを言ってる?↓みたいな感じで。 array.withUnsafeMutableBufferPointer { p in p = q }letで渡して欲しいね@escaping にキャプチャされることを防ぐためには inout が必要だけど、ポインタ自体の書き換えは封じられてるから、 inout のそれ自体を書き換えられる機能は要らないという理解。 return bp しちゃえば取り出せるからあんまり意味ないと思うreturn bp と意図せずやってしまうキャプチャとでは、後者だけ防げるのは意味がある気がする。inout を外すことを検討しても良さそうな気も。The issue with changing .swapTo (et al.?) to nonmutating is that semantically it really is a mutation. But pointers as collections have different mutation semantics to other collections: Mutating an Array’s storage is the same as mutating its value, whereas a pointer’s value is its address, not its storage. Making the Unsafe*Pointer MutableCollection methods themselves nonmutating probably wouldn’t be a source-breaking change (it’d just lower the “bar of entry” to include let constant instances too). I imagine this is noncontroversial.
https://forums.swift.org/t/why-does-the-withunsafemutablebufferpointer-closure-take-an-inout-parameter/6794/10 (edited)@escaping キャプチャ防止の話はされてなさそう?protocol P { // mutating func foo() } extension P { mutating func foo() { print("P") } } struct S: P { func foo() { print("S") } } let s: S = S() s.foo() // "S" var s2: S = S() s2.foo() // "S" var p: P = s p.foo() // "S"protocol P { // mutating func foo() } extension P { mutating func foo() { print("P") } } struct S: P { func foo() { print("S") } mutating func foo() { print("S2") } } let s: S = S() s.foo() // "S" var s2: S = S() s2.foo() // "S" var p: P = s p.foo() // "S" (edited)<stdin>:15:19: error: invalid redeclaration of 'foo()' mutating func foo() { ^ <stdin>:12:10: note: 'foo()' previously declared here func foo() { ^ (edited)S のままでは呼び出せないし。sort が MutableCollection にないのは、 Element が Comparable じゃないといけないからか。MutableCollection methods as nonmutatingimport Foundation func time(label: String, f: ()->Void) { let start = Date() f() print("\(label): elapsed time: ", Date().timeIntervalSince(start), "sec") } var x = [Int](0..<65536) x.withUnsafeMutableBufferPointer { bp in time(label: "Slice") { bp[0..<60000].sort() } time(label: "Rebase") { var rebase = UnsafeMutableBufferPointer(rebasing: bp[0..<60000]) rebase.sort() } } (edited)Stack dump: 0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -I /Libraries/.build/x86_64-unknown-linux/debug -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOSHA1/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOAtomics/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIODarwin/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOLinux/include -module-cache-path /Libraries/.build/x86_64-unknown-linux/debug/ModuleCache -O -D DEBUG -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOHTTPParser.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOSHA1.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOAtomics.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIODarwin.build/module.modulemap -Xcc -fmodule-map-file=/Libraries/.build/x86_64-unknown-linux/debug/CNIOLinux.build/module.modulemap -module-name main -lLibraries /usr/bin/swift[0x4626bd4] /usr/bin/swift[0x46249a0] /usr/bin/swift[0x4626d82] /lib/x86_64-linux-gnu/libpthread.so.0(+0x11390)[0x7fbbc7af7390] [0x7fbbc7f25d22] [0x7fbbc7f25837] [0x7fbbc7f24e3b] [0x7fbbc7f24d08] [0x7fbbc7f24af7] [0x7fbbc7f24862] [0x7fbbc7f242d3] /usr/bin/swift[0xcf1a7e] /usr/bin/swift[0xcf5c92] /usr/bin/swift[0x5162df] /usr/bin/swift[0x4eb215] /usr/bin/swift[0x4e66b6] /usr/bin/swift[0x48da2e] /lib/x86_64-linux-gnu/libc.so.6(__libc_start_main+0xf0)[0x7fbbc (edited)string1 += string2 はちゃんと string1 = string1 + string2 よりも効率的に実装されてるのか。 https://github.com/apple/swift/blob/master/stdlib/public/core/String.swift#L575-L577+= もかな。capacity を持っておいたいいってことか。as!によるキャストは真の型を実際に検証する。 (edited)public init(unsafeUninitializedCapacity:,initializingWith initializer:) これinit+末尾クロージャのみのケースではだったらどうするんだろう……let a = [0, 1, 2] a.withUnsafeBufferPointer { defer { print($0) } _ = $0 }let a = [0, 1, 2] a.withUnsafeBufferPointer { defer { print($0) } _ = $0 }swift-4.2.1-RELEASE/usercode/main.swift:4:15: error: anonymous closure argument not contained in a closure print($0) ^.zeroじゃなくて0書くだけで少し高速化できる。 (edited)let ptr = UnsafeMutablePointer<Int8>.allocate(capacity: len) ptr[0] = Int8(Character("n").asciiValue!) ptr[1] = Int8(Character("e").asciiValue!) ptr[2] = Int8(Character("k").asciiValue!) ptr[3] = Int8(Character("o").asciiValue!) ptr[4] = Int8(Character("\0").asciiValue!) let immutablePtr = UnsafePointer<Int8>(ptr)! let neko = String(cString: immutablePtr) (edited)CCharなんですよ。CCharがInt8のtypealiasなのでInt8に見えます。Character.asciiValueに関してはアスキーキャラクターコードが 0x00 - 0xFF だからだと思います。UTF8を受け取るCのAPIがUnsafePointer<UInt8>!とかになってたりするから、UTF8でもあるasciiValueもUInt8の方が便利そう。-Ounchecked ? (edited)-Ounchecked を提案してみた。protocol Protocol { associatedtype T1 associatedtype T2 func myFunc<Bar, Baz>(_: Bar) -> Class<Bar.T1, Baz> where Bar: Class<T1, T2> } class Class<T1, T2> : Protocol { func myFunc<Bar, Baz>(_: Bar) -> Class<Bar.T1, Baz> where Bar: Class<T1, T2> { } } このコードをコンパイルしようとすると Abort Trap:6 になるのですが、これって既知のバグでしょうか protocol Protocol { associatedtype T1 func myFunc<Bar>(_: Bar) -> Class<Bar.T1> where Bar: Class<T1> } class Class<T1> : Protocol { func myFunc<Bar>(_: Bar) -> Class<Bar.T1> where Bar: Class<T1> { } }protocol Protocol { associatedtype T1 func myFunc<Bar>(_: Bar) -> Class<Bar.T1> where Bar: Class<T1> } class Class<T2> : Protocol { func myFunc<Bar>(_: Bar) -> Class<Bar.T1> where Bar: Class<T2> { } }protocol Protocol { associatedtype T1 func myFunc<Bar>(_: Bar) -> Class<Bar.T1> where Bar: Class<T1> } class Class<T2> : Protocol { func myFunc<Bar>(_: Bar) -> Class<Bar.T1> where Bar: Class<T2> { } }swift-4.2.1-RELEASE/usercode/main.swift:4:43: error: reference to invalid associated type 'T1' of type 'Bar' func myFunc<Bar>(_: Bar) -> Class<Bar.T1> where Bar: Class<T1> ^ /usercode/main.swift:7:7: error: type 'Class<T2>' does not conform to protocol 'Protocol' class Class<T2> : Protocol { ^ /usercode/main.swift:2:20: note: protocol requires nested type 'T1'; do you want to add it? associatedtype T1 ^While emitting witness table for protocol conformance to ...が僕のと同じなので既知のBugでした、ありがとうございました swift struct ZeroRNG: RandomNumberGenerator { // Implements `mutating func next() -> UInt64` func next() -> UInt64 { return 0 } } let rng = ZeroRNG() print(rng.next()) var rng2 = rng print(Float.random(in: 0..<1, using: &rng2)) (edited)SystemRandomNumberGeneratorあたりにできなかった名残がありますが。 https://github.com/apple/swift/blob/master/stdlib/public/core/Random.swift#L157someでassociatedTypeの型を制限する @swift-5.1.5
protocol P1 { associatedtype A var a: A { get } } protocol AisInt: P1 where A == Int {} struct S<A>: P1 { var a: A } extension S: AisInt where A == Int {} func f1() -> some P1 { S(a: 1) } func f2() -> some AisInt { S(a: 1) } print(f1().a is Int) print(f2().a is Int)true truestderr:<stdin>:15:14: warning: 'is' test is always true print(f2().a is Int) ^someを使ってみようとしたけど、someがネストすると型推測がうまくいかず断念した。Publishers.DeferredはDeferredへ変更 Publishers.EmptyはEmptyへ変更 Publishers.FailはFailへ変更 Publishers.OnceはResult.Publisherへ変更 Publishers.OptionalはOptional.Publisherへ変更 Publisher型毎の特化実装メソッドが減る。 PublishedのpropertyWrapper仕様が更新(acceptされた最新ではない) keyPath map関連がFoundationからCombineへ移動。AnyCancellableをちゃんと保持しないと即座に解放される様になり、非同期なPublisherとかも解放されてしまい動かなくなった(たぶん正しい挙動になった)bar はString?として扱えるのすごいな @propertyWrapper public struct UserDefault<Value> { private let key: String private let defaultValue: Value private let defaults: UserDefaults public init(key: String, defaultValue: Value, defaults: UserDefaults = .standard) { self.key = key self.defaultValue = defaultValue self.defaults = defaults } public var wrappedValue: Value { get { (defaults.object(forKey: key) as? Value) ?? defaultValue } set { defaults.set(newValue, forKey: key) } } } final class A { @UserDefault(key: "foo", defaultValue: nil, defaults: .standard) var foo: String? @UserDefault(key: "bar", defaultValue: nil, defaults: .standard) var bar: String } (edited)CurrentValueSubjectは CoWとかしないんだね。let subject1 = CurrentValueSubject<Int, NSError>(1) let subject2 = subject1 subject1.value = 5 subject2.value == 5 // true (edited)Codable, Equatable, Hashableとか、その実装がコンパイラにより生成されたものを利用している、を保証する様な仕組みが欲しい気がする。func ==(P, P) が実装してあっても、 P? == P? はできないのですぐ詰まるAnySubscriberの実装が変わった。Subscriberが要求する3つのインスタンスメソッドを保持する事で型を消してたけど、Boxクラスを使う形式に変わってる。AnySubscriber周りで@inlinableが使われる様になったため、Xcode-beta.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/System/Library/Frameworks/Combine.framework/Modules/Combine.swiftmodule/x86_64.swiftinterfaceを見ると実装がほぼ丸見え。Dictionary.subscriptのdefaultは、mutatingメンバを使うとDictionaryへ登録できる。 @swift-5.0.3
class ClassBox { var name = "" } var classDictionary = [String: ClassBox]() classDictionary["test", default: ClassBox()].name = "name" print("classDictionary:", classDictionary) struct ValueBox { var name = "" } var valueDictionary = [String: ValueBox]() valueDictionary["test", default: ValueBox()].name = "name" print("valueDictionary:", valueDictionary) (edited)classDictionary: [:] valueDictionary: ["test": main.ValueBox(name: "name")] (edited)as? の右側のプロトコル部分を実行時に変えられる様にならない限りはそうなるのかな? (edited)func cast<T>(_ x: X, type: T.Type) -> X? { return x as? T } ↑こういうのはかけますよclass A { func foo() { } } class B <T> : A { override func foo(x: Any) { if let t = cast(x, T.self) { ... } } } func f(a: A) { a.foo() } (edited)class C {} func cast<P>(_ any: Any, _ type: P.Type) -> (C & P)? { any as? (C & P) }<stdin>:3:50: error: non-protocol, non-class type 'P' cannot be used within a protocol-constrained type func cast<P>(_ any: Any, _ type: P.Type) -> (C & P)? { ^ <stdin>:3:50: error: non-protocol, non-class type 'P' cannot be used within a protocol-constrained type func cast<P>(_ any: Any, _ type: P.Type) -> (C & P)? { ^ <stdin>:4:18: error: non-protocol, non-class type 'P' cannot be used within a protocol-constrained type any as? (C & P) ^as? の右側のプロトコル部分を実行時に変えられない」は合ってる? (edited)protocol P {} class A {} class B : A, P {} func f() -> A & P { return B() }as?によるキャストは普通の型の場合と protocol existentialの場合で全然別物が2種類あるのかな?Pの宣言はジェネリックパラメータとしてあるよ。 (edited)func f(_ x: Any) -> (A & P)? { return x as? A & P }protocol P {} func f<T>(_ x: Any, _ t: T.Type) -> (P & T)? { return x as? P & T } (edited)<stdin>:2:42: error: non-protocol, non-class type 'T' cannot be used within a protocol-constrained type func f<T>(_ x: Any, _ t: T.Type) -> (P & T)? { ^ <stdin>:2:42: error: non-protocol, non-class type 'T' cannot be used within a protocol-constrained type func f<T>(_ x: Any, _ t: T.Type) -> (P & T)? { ^ <stdin>:3:22: error: non-protocol, non-class type 'T' cannot be used within a protocol-constrained type return x as? P & T ^ (edited)@dynamicMemberLookupとかあるよ。 (edited)_swift_dynamicCastが呼ばれるな。 @swift-5.1.5
protocol P {} class C: P {} func cast(_ any: Any) -> (C & P)? { any as? (C & P) } _ = cast(C()) (edited)swift_conformsToSwiftProtocolImplの中で__swift5_protoセクションの中のレコードを探すところですけど、 for (const auto &record : section) { auto &descriptor = *record.get(); // We only care about conformances for this protocol. if (descriptor.getProtocol() != protocol) continue;void swift::initializeProtocolConformanceLookup() { REGISTER_FUNC( addImageCallback<TextSegment, ProtocolConformancesSection, addImageProtocolConformanceBlockCallback>); }#define REGISTER_FUNC(...) _dyld_register_func_for_add_image(__VA_ARGS__)When you call _dyld_register_func_for_add_image, the dynamic linker runtime calls the specified callback (func) once for each of the images that is currently loaded into the program. When a new image is added to the program, your callback is called again with the mach_header for the new image, and the virtual memory slide amount of the new image.protocol P {} class C: P {} func cast(_ any: Any) -> (C & P)? { any as? (C & P) } _ = cast(C()) これ、C & Pのメタデータを用意してキャストするコードが生成されるから、witness tableも持ってそう。Cが既にPだというのは考慮されていない感じ。_swift_dynamicCastに丸投げで、結果witness table不要となる可能性があるのかも。Array<Optional<T>> が一度作られるところの複雑度が高い気がするけど mapの方は ?? [] のところでArrayのカッコがまた出てくるのが気に食わん。mapの方だ。!があるのが嫌だけど直感的には一番わかりやすいですね
protocol P : AnyObject {} struct S<T: AnyObject> {} // 'S' requires that 'P' be a class type S<P>() (edited)protocol P : AnyObject {} class C : P {} struct S<T: AnyObject> {} var a: P = C() var b: AnyObject = a as AnyObjectP?のweak varも作れるんだよなあ。:AnyObjectの場合はstruct ClassExistentialContainer { HeapObject *value; WitnessTable *witnessTables[NUM_WITNESS_TABLES]; };struct Weak<T: AnyObject> { } ↑これに入れたかったprotocolを@objc protocolにすれば@objc使いたくないンゴねT: P をstrong参照 AnyP<X: P>はT: Pを内部でstrong参照 Weak<Y>はY = AnyP<T>を内部でweak参照WeakAnyPの実装が必要で、 これだとうまくいくんだなswift-5.1.2-RELEASEは出ないのかな。extension Optional { public mutating func consume<R>(_ f: (Wrapped) throws -> R) rethrows -> R? { guard let x = self else { return nil } self = nil return try f(x) }self.cameraCapture.consume { $0.dispose() } // ↓と同じ if let c = self.cameraCapture { c.dispose() self.cameraCapture = nil } (edited)guard let capture = (self.cameraCapture.consume { $0 }) else { return } use(capture) // ↓と同じ guard let capture = self.cameraCapture else { return } self.cameraCapture = nil use(capture)protocol Enum { static func associatedValue(_ value: String) -> Self static var singleValue: Self { get } } enum Foo: Enum { case associatedValue(String) case singleValue }protocol Enum { static func associatedValue(_ value: String) -> Self static var singleValue: Self { get } } enum Foo: Enum { static func associatedValue(_ value: String) -> Foo { _associatedValue(value) } static var singleValue: Foo { _singleValue } case _associatedValue(String) case _singleValue }class X { init(){} deinit { print("deinit") } } do { let x = X() print(x) } let x = X() print(x) (edited)class X { init(){} deinit { print("deinit") } } do { let x = X() print(x) } let x = X() print(x)swift-5.1-RELEASEmain.X deinit main.Xclass X { init(){} deinit { print("deinit") } } do { let x = X() print(x) } let x = X() print(x)swift-DEVELOPMENT-SNAPSHOT-2019-11-08-amain.X deinit main.X// c3.swift public protocol P { func foo() -> Int }; c3.ll ... @"$s2c31PMp" = constant <{ i32, i32, i32, i32, i32, i32, %swift.protocol_requirement }> <{ i32 65603, ... (edited)// c4.cpp #include <stdio.h> #include <stdlib.h> #include <dlfcn.h> int main() { void *handle = dlopen(nullptr, RTLD_LAZY); if (!handle) { printf("dlopen failed: %s\n", dlerror()); return 0; } void *symbol = dlsym(handle, "$s2c31PMp"); if (!symbol) { printf("symbol not found: %s\n", dlerror()); return 0; } int32_t flags = ((int32_t *)symbol)[0]; printf("flags=%d\n", flags); if (dlclose(handle)) { printf("dlclose failed: %s\n", dlerror()); return 0; } return 0; }$ clang++ -std=c++14 c4.cpp -c -S -emit-llvm $ ./c4.out flags=65603protocol EquatableOpener { init<T>(_ value: T) init<T: Equatable>(_ value: T) } func openEquatable<EO: EquatableOpener>(_ value: Any, openerType: EO.Type) -> EO { // 黒魔術 }AnyEquatable を openEquatableに渡せるstruct MyAnyHashable: Hashable { var originalHashValue: Int var originalTypeIdentifier: ObjectIdentifier init<H: Hashable>(_ origin: H) { self.originalHashValue = origin.hashValue self.originalTypeIdentifier = ObjectIdentifier(H.self) } } print(MyAnyHashable(1) == MyAnyHashable(1.0))Dictionary<AnyHashable, Any> だし。 (edited)NSNumber になるprint("hello")print("hello")swift-5.1.3-RELEASEhellostruct Cont<A, B> { var run: ((A) -> B) -> B var flatMap: (A) -> Cont<A, B> { get { fatalError() } _modify { let that = self var me: (A) -> Cont<A, B> = { (a: A) -> Cont<A, B> in that } yield &me let tmp = { (k: (A) -> B) -> B in that.run({ (a: A) -> B in me(a).run(k) }) } run = tmp } } } var a = Cont<Int, Int>( run: { (k: (Int) -> Int) -> Int in k(1) } ) a.flatMap = { (x: Int) -> Cont<Int, Int> in Cont<Int, Int>( run: { (k: (Int) -> Int) -> Int in k(x + 1000) } ) } a.flatMap = { (x: Int) -> Cont<Int, Int> in Cont<Int, Int>( run: { (k: (Int) -> Int) -> Int in k(x + 2000) } ) } a.run( { (a: Int) in print(a) return a } )struct Cont<A, B> { var run: ((A) -> B) -> B var flatMap: (A) -> Cont<A, B> { get { fatalError() } _modify { let that = self var me: (A) -> Cont<A, B> = { (a: A) -> Cont<A, B> in that } yield &me let tmp = { (k: (A) -> B) -> B in that.run({ (a: A) -> B in me(a).run(k) }) } run = tmp } } } var a = Cont<Int, Int>( run: { (k: (Int) -> Int) -> Int in k(1) } ) a.flatMap = { (x: Int) -> Cont<Int, Int> in Cont<Int, Int>( run: { (k: (Int) -> Int) -> Int in k(x + 1000) } ) } a.flatMap = { (x: Int) -> Cont<Int, Int> in Cont<Int, Int>( run: { (k: (Int) -> Int) -> Int in k(x + 2000) } ) } a.run( { (a: Int) in print(a) return a } )swift-5.1.3-RELEASE3001/usercode/main.swift:31:3: warning: result of call to function returning 'Int' is unused a.run( { (a: Int) in ^ ~~~~~~~~~~~~~~~$ swiftc yield.swift -emit-sil Run module pass #0, stage Guaranteed Passes, pass 0: SILGenCleanup (silgen-cleanup) Start function passes at stage: Guaranteed Passes Run #1, stage Guaranteed Passes, pass 1: DiagnoseInvalidEscapingCaptures (diagnose-invalid-escaping-captures), Function: $s5yield4NekoC4_bow33_BFC072E4B657A1986E9E174ACA620350LLSSvpfi Run #2, stage Guaranteed Passes, pass 2: DiagnoseStaticExclusivity (diagnose-static-exclusivity), Function: $s5yield4NekoC4_bow33_BFC072E4B657A1986E9E174ACA620350LLSSvpfi Run #3, stage Guaran # 中略 Run #135, stage Guaranteed Passes, pass 20: YieldOnceCheck (yield-once-check), Function: $s5yield4NekoC3bowSSvM yield.swift:9:13: error: accessor must not yield more than once yield &_bow ^ yield.swift:8:13: note: previous yield was here yield &_bow ^ Run #136, stage Guaranteed (edited)func factorial(of n: Int) -> Int { func f(_ n: Int, _ r: Int) -> Int { n <= 1 ? r : f(n - 1, r * n) } return f(n, 1) }@inline(__always) func factorial(of n: Int) -> Int { func f(_ n: Int, _ r: Int) -> Int { n <= 1 ? r : f(n - 1, r * n) } return f(n, 1) } print(factorial(of: 5))define i32 @main(i32, i8** nocapture readnone) local_unnamed_addr #0 { entry: ... %._value = bitcast %swift.refcounted* %13 to i64* store i64 120, i64* %._value, align 8 ... ret i32 0 }120 まで計算されて埋め込まれてる。print(factorial(of: [5].randomElement()!))Generic<T> であっても構成する静的な経路によって T の conformance が変わるんだなあ let topMargin = 190 NSLayoutConstraint.activate([ contentViewController.view.topAnchor.constraint(equalTo: view.topAnchor, constant: topMargin), ... ^ こういう場合の topMargin をIntじゃなくてCGFloatに推測してくれるようにならないかな。右辺を別の行まで拡大する、みたいな。import scala.language.implicitConversions class A(val value: Int) {} implicit def toA(value: Int): A = new A(value) def f(x: A): Int = x.value * 2 val a = 100 val y = f(a) println(y) // 200 このとき、aの型はIntです。 暗黙的に関数が呼ばれるだけなので、型推論に影響を及ぼしているわけではないと思います。 (久しぶりにScala書きました。間違ってたらすみません) (edited)let topMargin = 190 // ここの左辺の型を右辺からじゃなくて、 ...constraint(equalTo: view.topAnchor, constant: topMargin) // ここの代入から推論してくれてもいいんじゃない? だったんですけど、let topMargin = 190 // ここは右辺からIntと推論 topMargin) // ここでCGFloat(190) を暗黙的によぶ ということだと思うので、厳密には違いそう。 (edited)...constraint(equalTo: view.topAnchor, constant: 190) これと同じ扱いにしてほしい、という考えで要するにリテラルからの場合のみ、ということになるはずなので行けると思ってるんですよね。let mut v = Vec::new(); let a: u32 = 1; v.push(a);func f() -> Int { print(1); return 0 } func f() -> String { print(2); return "" } let a: Int = f() ↑こういうのは動的にやるのは無理だけど、動的言語でも事前検査してディスパッチを書き換える事はできると思う。objc_directとかを使える様になってる。 https://nshipster.com/direct/ (edited)@property(direct)が通る事を確認した。Notes on Approach The key idea here is using the bytes of a UInt64 in a way similarly to SIMD. When doing ASCII operations the new UTF-8 backing of Strings makes them perfectly suited for this technique. Aside from integer parsing, for example also ASCII case manipulation sees many-X speed-ups when using this approach. Example (details below): let str = 0x3132_3030_3633_3739 // ASCII "12006379" let digits = str &- 0x3030_3030_3030_3030 // Subtract "0" from every lane // … (underflow check omitted for clarity) let c = (0x7f - 9) &* 0x0101_0101_0101_0101 // Constant to check value > 9 let isAnyAbove9 = (digits &+ c) & 0x8080_8080_8080_8080 != 0@UIApplicationMain とかをユーザーが自作できるようにするやつ、急にピッチ来たと思ったら急に審査来てた。@UIApplicationMain が出てきた時、いったいどうやって起動してるのかわからなくなったから、 昔の main.m が生成されて、その中に UIApplicationMain 関数の呼び出しが普通に書いてあるやつのほうが好きだった (edited)func f(_ aa: Int = 0, _ bb: Int) {} f(1)<stdin>:2:4: error: missing argument for parameter #2 in call f(1) ^ , <#Int#> <stdin>:1:6: note: 'f' declared here func f(_ aa: Int = 0, _ bb: Int) {} ^func f(_ aa: Int = 0, _ bb: Double) {} f(1.0)<stdin>:2:3: error: missing argument for parameter #1 in call f(1.0) ^ <#Int#>, <stdin>:1:6: note: 'f' declared here func f(_ aa: Int = 0, _ bb: Double) {} ^#1 になってる。aa が missing なのは許されるはずか。func f(_ aa: Int = 0, _ bb: Double) {} let bb: Double = 1.0 f(bb)<stdin>:4:3: error: missing argument for parameter #1 in call f(bb) ^ <#Int#>, <stdin>:1:6: note: 'f' declared here func f(_ aa: Int = 0, _ bb: Double) {} ^<stdin>:4:3: error: missing argument for parameter #1 in call f(bb) ^ <#Int#>, <stdin>:1:6: note: 'f' declared here func f(_ aa: Int = 0, _ bb: Double) {} ^<stdin>:4:5: error: missing argument for parameter #2 in call f(bb) ^ , <#Double#> <stdin>:1:6: note: 'f' declared here func f(_ aa: Int = 0, _ bb: Double) {} ^bb は Double だから省略されてるのは aa だとラベルなくても判断できるけど、エラーで正しいでいいのかな?-debug-constraints 見ると、masterの挙動だと、 synthesize missing argument fixだけじゃなくて、allow argument to parameter type conversion mismatch fix も生成されていてfunc f(_ aa: Int..., _ bb: Double) {} なのでこの制限があるんですね。<stdin>:1:22: error: a parameter following a variadic parameter requires a label func f(_ aa: Int..., _ bb: Double) {} ^func f(_ aa: Int = 0, _ bb: Int) { print(1) } func f(_ bb: Int) { print(2) } f(1)func f(_ bb: Double) {} func f(_ aa: Int, _ bb: Double) {} f(1.0)func f(_ aa: Int = 0, _ bb: Int) { print(1) } にはマッチしないんだから、 func f(_ bb: Int) が選ばれるのは自然なんじゃないの?func f(_ aa: Int = 0, _ bb: Int) にマッチしないのがバグだとみなすなら、意地悪だなと思いました。 (edited)func f(_ aa: Int = 0, _ bb: Int) {} // ↑が↓のオーバーロードを意味していると捉えるなら func f(_ bb: Int) {} func f(_ aa: Int, _ bb: Int) {} // 並べるなら下つじゃないと変。 (edited)func f(_ aa: Int, _ bb: Int = 0) { print(1) } func f(_ bb: Int) { print(2) } f(1)comparing solutions 1 and 0 Comparing declarations func f(_ bb: Int) { } and func f(_ aa: Int, _ bb: Int = 0) { } (isDynamicOverloadComparison: 0) (found solution 0 0 0 0 0 0 0 0 0 0 0 0 0) comparison result: better Comparing declarations func f(_ aa: Int, _ bb: Int = 0) { } and func f(_ bb: Int) { } (isDynamicOverloadComparison: 0) comparison result: not better comparing solutions 1 and 0protocol P { func f(_: Int) func f(_: Int, _: Int) } struct S: P { func f(_ aa: Int, _ bb: Int = 0) { print(1) } } let s: S = S() s.f(42)<stdin>:6:8: error: type 'S' does not conform to protocol 'P' struct S: P { ^ <stdin>:2:10: note: protocol requires function 'f' with type '(Int) -> ()'; do you want to add a stub? func f(_: Int) ^protocol P { func f(a: Int) } struct S: P { func f(a: Int, b: Int = 0) {} }<stdin>:4:8: error: type 'S' does not conform to protocol 'P' struct S: P { ^ <stdin>:2:8: note: protocol requires function 'f(a:)' with type '(Int) -> ()'; do you want to add a stub? func f(a: Int) ^protocol P { func f(a: Int) func f(a: String) } struct S: P { func f<T>(a: T) {} }protocol P { func f(_: Int, _: Int) } extension P { func f(_ aa: Int) { print(2) } } struct S: P { func f(_ aa: Int, _ bb: Int = 0) { print(1) } } let s: S = S() s.f(42)protocol P { func f(_: Int, _: Int) } extension P { func f(_ aa: Int) { print(2) } } struct S: P { func f(_ aa: Int, _ bb: Int = 0) { print(1) } } let s: S = S() s.f(42) let p: P = s p.f(42)protocol P { func f(_: Int) func f(_: Int, _: Int) } extension P { func f(_ aa: Int) { print(2) } } struct S: P { func f(_ aa: Int, _ bb: Int = 0) { print(1) } } let s: S = S() s.f(42) let p: P = s p.f(42)protocol P { func f(_: Int) func f(_: Int, _: Int) } extension P { func f(_ aa: Int) { print(2) } } struct S: P { func f(_ aa: Int) { print(3) } func f(_ aa: Int, _ bb: Int = 0) { print(1) } } let s: S = S() s.f(42) let p: P = s p.f(42)class C1 { func f(_ aa: Int) { print(1) } func f(_ aa: Int, _ bb: Int) { print(2) } } class C2: C1 { override func f(_ aa: Int, _ bb: Int = 0) { print(3) } } let c2: C2 = C2() c2.f(42) let c1: C1 = c2 c1.f(42)Comparing declarations func f(_ aa: Int) { } and func f(_ aa: Int, _ bb: Int = 0) { } (isDynamicOverloadComparison: 0) comparison result: not better Comparing declarations func f(_ aa: Int, _ bb: Int = 0) { } and func f(_ aa: Int) { } (isDynamicOverloadComparison: 0) comparison result: better comparing solutions 0 and 1--- Solution #0 --- locator@0x7fd8578d8e00 [DeclRef@b.swift:15:3] with b.(file).main(a:).a@b.swift:14:11 as a: S --- Solution #1 --- locator@0x7fd8578d8e50 [UnresolvedDot@b.swift:15:5 -> member] with b.(file).P extension.f@b.swift:7:8 as S.f: (Int) -> () Opened types: locator@0x7fd8578d8e50 [UnresolvedDot@b.swift:15:5 -> member] opens τ_0_0 -> $T4P.f の呼び出しは実際には func f<Self>(self: Self, _ aa: Int) の呼び出しだから (edited)print する値もそろえてみた。 @swift-main
protocol P { func f(_: Int) func f(_: Int, _: Int) } extension P { func f(_ aa: Int) { print(1) } } struct S: P { func f(_ aa: Int, _ bb: Int = 0) { print(2) } } let s: S = S() s.f(42) let p: P = s p.f(42) ////////////////////// class C1 { func f(_ aa: Int) { print(1) } func f(_ aa: Int, _ bb: Int) { print(999) } } class C2: C1 { override func f(_ aa: Int, _ bb: Int = 0) { print(2) } } let c2: C2 = C2() c2.f(42) let c1: C1 = c2 c1.f(42)func f(_ aa: Int..., bb: String = "", _ cc: Double) {} func main(i: Int, d: Double) { f(i, i, i, d) }<stdin>:4:9: error: missing argument for parameter #3 in call f(i, i, i, d) ^ , <#Double#> <stdin>:1:6: note: 'f(_:bb:_:)' declared here func f(_ aa: Int..., bb: String = "", _ cc: Double) {} ^ <stdin>:4:14: error: cannot convert value of type 'Double' to expected argument type 'Int' f(i, i, i, d) ^ Int( )d だけ #3 に対応させるしか無いはず。func f(_ aa: Int..., bb: String = "", _ cc: Double) {} は少なくとも現状は通らないようにすべきだ。bb: を与えて区切れるから書けても良くないですか?func f(_ aa: Int = 0, _ bb: Int) {} f(1, 2)= 0 は無駄なので警告かエラーがいいかと。func foo(a a1: Int = 1, a a2: Int) {} (edited)func f(aa a1: Int = 1, aa a2: Int) {} f(aa: 2)<stdin>:2:8: error: missing argument for parameter 'aa' in call f(aa: 2) ^ , aa: <#Int#> <stdin>:1:6: note: 'f(aa:aa:)' declared here func f(aa a1: Int = 1, aa a2: Int) {} ^@_disfavoredOverload 使っててウケる。@_disfavoredOverload が付いてたら、それを呼ぶ側が知らない場合、こっちが呼ばれるはずだけどなぜかこっち、みたいな混乱が起こりますか?Text("hoge") みたいな、文字列リテラルを与えたケースの優先度がひっくり返ってる@overloadPrecedence(800) みたいなので決められるのがいいんじゃないか。@favoredOverload(1) @favoredOverload(2) とかで数字が大きい方に吸い込まれるならわかりやすそう。protocol P1 { func f(a: Int) } protocol P2 { func f(a: Double) } func main(x: P1 & P2) { x.f(a: 0) }#2 になるやつ) はめっちゃピンポイントな特別実装がされてた。func f(x: String, _ aa: Int = 0, _ bb: Double) {} f("", 42.0)
<stdin>:2:3: error: missing argument for parameter 'x' in call f("", 42.0) ^ x: <#String#>, <stdin>:1:6: note: 'f(x:_:_:)' declared here func f(x: String, _ aa: Int = 0, _ bb: Double) {} ^ <stdin>:2:3: error: cannot convert value of type 'String' to expected argument type 'Int' f("", 42.0) ^func f(x: String, _ aa: Int = 0, _ bb: Double) {} f(x: "", 42.0)<stdin>:2:14: error: missing argument for parameter #3 in call f(x: "", 42.0) ^ , <#Double#> <stdin>:1:6: note: 'f(x:_:_:)' declared here func f(x: String, _ aa: Int = 0, _ bb: Double) {} ^ <stdin>:2:10: error: cannot convert value of type 'Double' to expected argument type 'Int' f(x: "", 42.0) ^ Int()<stdin>:2:14: error: missing argument for parameter #3 in call f(x: "", 42.0) ^ , <#Double#> <stdin>:1:6: note: 'f(x:_:_:)' declared here func f(x: String, _ aa: Int = 0, _ bb: Double) {} ^ <stdin>:2:10: error: cannot convert value of type 'Double' to expected argument type 'Int' f(x: "", 42.0) ^ Int()<stdin>:2:14: error: missing argument for parameter #3 in call f(x: "", 42.0) ^ , <#Double#> <stdin>:1:6: note: 'f(x:_:_:)' declared here func f(x: String, _ aa: Int = 0, _ bb: Double) {} ^#2 と #3 になってない・・・。func f(a: Int, b: String) {} f(a: "a")<stdin>:2:3: error: missing argument for parameter 'a' in call f(a: "a") ^ a: <#Int#>, <stdin>:1:6: note: 'f(a:b:)' declared here func f(a: Int, b: String) {} ^a: は渡してるのにwa と b は解消されても a と a は元に戻っちゃうよね?ということ。[0] と [1] だけに対応が入ってるけど[0] と [1] 以外でも同じ問題は起こり得るよね?それこそさっきの異なるラベルの第一引数を入れるとか。[0] と [1] だけ対応したんだろう?UIView.animate(withDuration: 0.3) { self.view.alpha = 0 } completion: { _ in self.view.removeFromSuperview() }
animations: は書かないけど completion: は書くの?animations が本体で completion は付随する処理てきなイメージなのかな?そういう場合に使う想定?UIView.animate(withDuration: 0.3, animation: { self.view.alpha = 0 }) { self.view.removeFromSuperview() } も相変わらず書けるので、想定の呼び出し方を強制するものでもないですね。UIView.animate の場合は 奇跡的にその仕様でも自然に見えるな・・・.animate( が animationの指定の部分のタイトルっぽく見えるから・・・UIView.animate(withDuration: 0.3) animation: { self.view.alpha = 0 } completion: { _ in self.view.removeFromSuperview() } ↑こう書きたいな。Button { print("hello world") } label: { HStack { ... } } SwiftUIだとこんな感じになるのかなaction 後ろの方が良さそうに見えますね。ipAddressPublisher .sink receiveCompletion: { completion in // handle error }
() ない場合、ラベル書けると気持ち悪いですね。 < Alternatives Consideredで否定_ の場合だけこの機能使えるとかの方がいいんじゃないかな?UIView.animate の場合は+ (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations completion:(void (^ __nullable)(BOOL finished))completion API_AVAILABLE(ios(4.0)); // delay = 0.0, options = 0 + (void)animateWithDuration:(NSTimeInterval)duration animations:(void (^)(void))animations API_AVAILABLE(ios(4.0)); // delay = 0.0, options = 0, completion = NULLipAddressPublisher .sink() receiveCompletion: { completion in // handle error }_ でないと trailing closure 禁止でいい気がする・・・UIView.animate { } もだめになって: も省略しちゃえば func if(_ condition: Bool, _ body: () -> Void, else: () -> Void) { ... } if(foo) { ... } else { ... } とかできるけど、 Swift でやることじゃないね。 (edited){} 省略とかだとなんとかならないかな?LABEL: { } が今通らないなelse if を↑の枠組みでどう書くか。else_if 版をオーバーロードかなあ。{} で書きたいケースもあるからfunc foo(_ x: @autoclosure () -> Int) { print(x()) } foo { 42 }<stdin>:3:5: error: cannot convert value of type '() -> Int' to expected argument type 'Int' foo { 42 } ^func foo(_ x: @autoclosure () -> Int) { print(x()) } foo({ 42 }) (edited)<stdin>:2:5: error: function produces expected type 'Int'; did you mean to call it with '()'? foo({ 42 }) ^~~~~~ () (edited)func foo(_ x: @autoclosure () -> Int) { print(x()) } foo(42)String result = MessageFormat.format( "At {1,time} on {1,date}, there was {2} on planet " + "{0,number,integer}.", arguments);[T] なのか T, T, T,... へのsplatなのかわからない。$ cat AmbiguousVarArgs.java public class AmbiguousVarArgs { public static void main(String[] args) { String[] ss = { "XYZ" }; foo(ss); } static <T> void foo(T... xs) { System.out.println(xs); } } $ javac AmbiguousVarArgs.java Note: AmbiguousVarArgs.java uses unchecked or unsafe operations. Note: Recompile with -Xlint:unchecked for details. $ javac -Xlint:unchecked AmbiguousVarArgs.java AmbiguousVarArgs.java:7: warning: [unchecked] Possible heap pollution from parameterized vararg type T static <T> void foo(T... xs) { ^ where T is a type-variable: T extends Object declared in method <T>foo(T...) 1 warning $ java AmbiguousVarArgs [Ljava.lang.String;@7852e922String[] ss の文字列表現、に見えます。foo(T... xs) { のxsには配列が渡るんじゃないですか?printf は可変長だけど。println(Object x) が呼ばれたんだな。System.out が PrintStream だったか自信がなくなったけど大丈夫でした。 https://docs.oracle.com/javase/jp/8/docs/api/java/lang/System.html#outxs が String[][] になる可能性があると思います。 (edited)Object だからおかしいか。xs が 第一要素に String[] が入った Object[] になるのか、 Object[] にアップキャストされた String[] になるのかの曖昧さ?Object[] に String[] を入れられるんですけど、ミュータブルなのでぶっ壊れます。 $ cat BrokenCovariance.java import java.util.Arrays; public class BrokenCovariance { public static void main(String[] args) { String[] ss = { "XYZ" }; Object[] os = ss; // OK System.out.println(Arrays.toString(os)); os[0] = 42; // Can be compiled, but causes runtime error System.out.println(Arrays.toString(os)); } } $ javac BrokenCovariance.java $ java BrokenCovariance [XYZ] Exception in thread "main" java.lang.ArrayStoreException: java.lang.Integer at BrokenCovariance.main(BrokenCovariance.java:10)List は use-site variance で covariant にしたら add が消えたりして上手く動くんですけどね。import java.util.*; public class CovariantLists { public static void main(String[] args) { { // Invariant List<String> ss = new ArrayList<>(); ss.add("XYZ"); // OK List<Object> os = ss; // compile error } { // Covariant List<String> ss = new ArrayList<>(); List<? extends Object> os = ss; // OK os.add(42); // compile error } } } (edited)? extends の記法の奇抜さが良くなかった気も・・・。Covariance if A is a subtype of B then: Java: L<A> is a subtype of L<? extends B> (use-site) Scala: L[A] is a subtype of L[_ <: B] (use-site) L[A] is a subtype of L[+B] (declaration-site) Contravariance if A is a supertype of B then: Java: L<A> is a subtype of L<? super B> (use-site) Scala: L[A] is a subtype of L[_ >: B] (use-site) L[A] is a subtype of L[-B] (declaration-site) [_ <: T] 確かに extends superは難しいけど、これはわかる気がしないでもない。_ がいろんなところで出てくるからそういう意味で受け取りやすいかもな。? は唐突なんだよなList<? super Animal> とか、 Java 書いてる人の半分は理解してないと思う。[ ] なのが異端で目が慣れるまでちょっと怖いT と T? とかがあるけどOptional は tagged union だから本来 T と T? には型の派生関係はないはずなんよね。Optional にだけ特別にサブタイピングを認めてる。struct Foo<T> { case bar(T) case baz(T) }T is Foo<T> は成り立たない。() -> () is () -> throws () があります。T is Result<T, Swift.Error> が、 Func<A, R> の R でだけ発生する() throws -> Errorthrows E と -> E が区別されてるからthrows は tagged と untagged のあいのこなのか。map { $0 as T } / some(T) の優先順位を定義しなければいけなくなる (edited)import Foundation struct Test: Codable { let a = 5 } struct Test2: Codable { var a = 5 } let json = """ { "a": 10 } """.data(using: .utf8)! let test = try JSONDecoder().decode(Test.self, from: json) let test2 = try JSONDecoder().decode(Test2.self, from: json) print(test.a) print(test2.a)struct S { let a: Int = 1 } S(a: 2)<stdin>:2:6: error: argument passed to call that takes no arguments S(a: 2) ^let プロパティに初期値設定したらイニシャライザでも書き換えられないから JSON の値が反映されないのは仕方ないとして、 @swift-5.2.5
struct Foo { let a = 5 init(a: Int) { self.a = a } }<stdin>:4:16: error: immutable value 'self.a' may only be initialized once self.a = a ^ <stdin>:2:9: note: initial value already provided in 'let' declaration let a = 5 ^ <stdin>:2:5: note: change 'let' to 'var' to make it mutable let a = 5 ^~~ varimport Foundation struct Foo: Codable { let a = 5 } print(String(data: try! JSONEncoder().encode(Foo()), encoding: .utf8)!)struct A { init() { print("A.init") } } struct S { let a: A = A() init() { print("S.init") } } S()A.init S.initstderr:<stdin>:12:1: warning: result of 'S' initializer is unused S() ^~~import Foundation struct Foo: Codable { let a = 5 } let json = """ {"a":2} """ let foo = try! JSONDecoder().decode(Foo.self, from: json.data(using: .utf8)!) print(String(data: try! JSONEncoder().encode(foo), encoding: .utf8)!) (edited)let だから Codable の対象外とかもできないし。func function(@autoclosure @mustCalled completion: () -> Void) { completion() } もし、関数内で別の関数のクロージャ中で呼ばれないといけないときは、その別の関数のクロージャがmustCalledならコンパイル通る func function1(@autoclosure @mustCalled completion: () -> Void) { function2 { completion() } } func function2(@autoclosure @mustCalled completion: () -> Void) { completion() } 的な(日本語怪しくてすいません)$ swiftc bug.swift bug.swift:7:1: error: the compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions print((value.0 == values.0) && (value.1 == values.1) && (value.2 == values.2) && (value.3 == values.3)) ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~$ swiftc bug.swift bug.swift:7:14: error: value of type 'Int' has no member '0' print((value.0 == values.0) && (value.1 == values.1) && (value.2 == values.2) && (value.3 == values.3)) ~~~~~ ^ bug.swift:7:26: error: value of type '[Int]' has no member '0' print((value.0 == values.0) && (value.1 == values.1) && (value.2 == values.2) && (value.3 == values.3)) ~~~~~~ ^ bug.swift:7:39: error: value of type 'Int' has no member '1' print((value.0 == values.0) && (value.1 == values.1) && (value.2 == values.2) && (value.3 == values.3)) ~~~~~ ^ bug.swift:7:51: error: value of type '[Int]' has no member '1' print((value.0 == values.0) && (value.1 == values.1) && (value.2 == values.2) && (value.3 == values.3)) ~~~~~~ ^ bug.swift:7:64: error: value of type 'Int' has no member '2' print((value.0 == values.0) && (value.1 == values.1) && (value.2 == values.2) && (value.3 == values.3)) ~~~~~ ^ bug.swift:7:76: error: value of type '[Int]' has no member '2' print((value.0 == values.0) && (value.1 == values.1) && (value.2 == values.2) && (value.3 == values.3)) ~~~~~~ ^ bug.swift:7:89: error: value of type 'Int' has no member '3' print((value.0 == values.0) && (value.1 == values.1) && (value.2 == values.2) && (value.3 == values.3)) ~~~~~ ^ bug.swift:7:101: error: value of type '[Int]' has no member '3' print((value.0 == values.0) && (value.1 == values.1) && (value.2 == values.2) && (value.3 == values.3)) ~~~~~~ ^typealias TestCase = (input: (Bit, Bit, Bit, Bit, Bit, Bit), expected: Bit) let testBitResultBit: [TestCase] = //...enum じゃなかったんですよね。enum の case が camelCase じゃなく CamelCase だったってのが意外と理由かもしれませんねdeinit は効かなくなるけど、やれんかなぁ(1, 2) と (2, 1) どう比較するんだ? (1) < (1, 2) ?(directionScore, distanceScore) でソートするってのをやった。 sort のクロージャを書かないといけなかったけど、これが使えたら書かなくて良さそう。--use-integrated-swift-driverオプションが追加されています。"".data(using: .utf8) . <= ここで補完にでてくるのは`write(to:)`を選ぶと"".data(using: .utf8) ?.write(to: savePath) ^ オプショナルの?をつけてくれるんだけどそうするとここで改行ができなくなるからコンパイルエラーになるな (edited)try expected .data(using: .utf8)? .write(to: loadPath)?.write( ... の方がベター?sorted ((Result, Result) -> Bool, (Element) -> Result) ほしい(他の言語にはあった気がする、忘れた) こんなかんじで、比較対象を重複して書かなくていい // 面積でソート [CGRect()].sorted(<, { $0.width * $0.height }) (edited)extension Collection { func sorted<Result: Comparable>(_ comparing: (Result, Result) -> Bool, _ data: (Element) -> Result) -> [Element] { sorted { comparing(data($0), data($1)) } } } // 面積 [CGRect()].sorted(<, { $0.width * $0.height }) とりあえず考えてみたものの単純な例を実装してみた(Comparableだけど) (edited)P から any P に変更するという仕様変更ですcat as Hogeable がアップキャストっぽく見えるけど、 実際には Hogeable の existential への格納と言ったほうが近いのでcat as any Hogeable って書いてあったらもうちょっととっかかりやすいんじゃないかなあ。any Hogeable 型のコンテナにオブジェクトを格納するときにメソッドを埋めないといけなくてそれをどこから持ってくるかという話なので。4 as Double // fine 4 as! Double // crashes
https://oleb.net/2020/as/ これ面白かった。foo .bar .baz って書きますけど、 ?. のときは↓ですか? foo? .bar? .baz?. が不可分じゃないのおもしろいね。 ? は独立した後置演算子だったし。 (edited)foo?() とかもあるからfoo? が廃止されただけで。let f: (() -> ())? = { print("hello") } f? () (edited); がない言語はそのあたりの厳密なルールの理解が難しい。objc_* を呼んで好き勝手できる(し、ObjCのクラスを呼び出すライブラリもアプリに内蔵されてる)んですが、そういうのが許されているので、(個人的な解釈ですが) Apple的にはたぶんユーザーに書かせる分には良いんじゃないかと思うんですよねlet dict = [ "a": 2, "b": 3, "c": 5 if isFoo, ] みたいなの。#if したい みたいな話は見覚えがあるvar にして組み立てることになる。let dict = { var d = [:] ... return d }() こうするとvar性の延長は避けられるか。// Function Builder let dict: [String: Int] = .init { ("a", 2) ("b", 3) if isFoo { ("c", 5) } } (edited)let dict: [String: Int] = .init { [ "a": 2, "b": 3, ] if isFoo { ["c": 5] } }callAsFunction と組み合わせれば↓みたいなこともできる? let dict = [ "a": 2, "b": 3, ] { if isFoo { ["c": 5] } }callAsFunction 版の難点か。VStack { let foo = ... Text(foo) Text(foo) }if let はサポートされたはず。 (edited)if foo != nil { Text(foo!) }if let foo = foo { Text(foo) }=> オペレータを自作すれば今も一応・・・!= nil 書く度に //FIXME 付けてるfunc =><T, R>(_ f: (T) -> R) -> RVStack { ... => { (foo) in Text(foo) Text(foo) } }=> の ViewBuilder版が必要だwmap だと ViewBuilder にならなくないですか?.some(foo).map { } ?extension Optional where Element: View { func map<T, U: View>(_ f: @ViewBuilder (T) -> U) }extension Optional where Element: View { @ViewBuilder func map<T, U: View>(_ f: @ViewBuilder (T) -> U) }@ViewBuilder 付ける文法あるんですか?@ViewBuilder var body: some View { ... }rethrows 的な re@ViewBuilder がほしくなるねwif let が使えれば解決なわけで、 5.3 で問題ないはず?let dict: [String: Int] = .init { [ "a": 2, "b": 3, ] if isFoo { ["c": 5] } }buildBlock って可変長引数対応してるのかな?Dictionary は可変長でいけそう。 (edited)@_functionBuilder public struct DictionaryBuilder<Key: Hashable, Value> { public func buildBlock() -> [Key: Value] { [:] } public func buildBlock(_ c0: [Key: Value]) -> [Key: Value] { c0 } public func buildBlock(_ c0: [Key: Value], _ c1: [Key: Value]) -> [Key: Value] { c0.merging(c1) { _, new in new } } } extension Dictionary { public init(@DictionaryBuilder<Key, Value> _ builder: () -> [Key: Value]) { self = builder() } }import XCTest @testable import DictionaryBuilder final class DictionaryBuilderTests: XCTestCase { func testExample() { let dictionary: [String: Int] = .init { [ "a": 2, "b": 3, ] [ "c": 5, "d": 7, "e": 11, ] } XCTAssertEqual(dictionary, [ "a": 2, "b": 3, "c": 5, "d": 7, "e": 11, ]) } }init はあやしいかと思って static func にしてみたけど変わらず。buildBlock() 群を static func にする必要がありますね。 (edited)buildBlock を定義する」時だけの謎挙動を踏んでる気がする (edited)@_functionBuilder public struct DictionaryBuilder<Key: Hashable, Value> { public static func buildBlock(_ contents: [Key: Value]...) -> [Key: Value] { contents.reduce(into: [:]) { $0.merge($1) { _, new in new } } } } let dictionary: [String: Int] = .init { [ "a": 2, "b": 3, ] if isFoo { ["c": 5] } }buildIf が Alternative Considered になってる一方、 buildDo とかも載ってて、何が今使えるものなのかわからない・・・。async/await を比較した場合、 suspendAsync(...) に相当するのは new Promise(...) で、 beginAsync に相当するのは await なしでのコールかな? https://gist.github.com/lattner/429b9070918248274f25b714dcfc7619beginAsync だと中に複数の非同期関数のコールを書けるからちょっと違う? beginAsync 相当は↓みたいな感じ? (async () => { await foo(); await bar(); })(); // ここでは await なしでコール (edited)suspend fun はコールサイトでのマーク( try とか await 的な)は特に必要ないのか。 Java の throws 相当に近いな(コールサイトのマークが必要ないけど suspend / throws が静的にチェックされるという意味で)。suspend を静的にチェックするなら throws もチェックしてくれればよかったのに・・・。そこが一番辛いんだよなぁ。suspendAsync と new Promise に対応してそう。 https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.coroutines.experimental/suspend-coroutine.htmllaunch はこっちか。 https://kotlin.github.io/kotlinx.coroutines/kotlinx-coroutines-core/kotlinx.coroutines/launch.htmlawait のマークが無いな。await あるほうが可読性高そうだけど・・・。ぱっと見でどこで await になってるかわからないのって結構怖そう・・・。async func foo() { (await?) f1() (await?) f2() (await?) f3() }render() があったとして、 await の直後には必ず render() を入れたいとかがあるかなあ? でもそれは状態の変化の方で呼び出しておけばいいしなあ。func foo() async { guard let first = self.values.first else { return } ... bar() if self.values.count == 1 { ... } else { ... } } みたいなのがあったときに、 bar が async だと values が空でないことが保証できないとか。bar が async だったとして、 ほかの非同期タスクの影響でも values が変更されうるようなシナリオって、 そもそも認知負荷が高すぎて考慮しきれないから、避けちゃう。async じゃなかったときは心配しないでそういうコードを書くことができる」async に集約されれば async でないことが同期であることの保証になるのか。async でも await が可視なら、 await から await までの間は同様の保証が働くということでした。await が不可視なのは怖いかなぁと。try がなくてジャンプが不可視なのもだけど、 await はより怖い感覚があるなぁ。any 導入されたら some Animal と any Animal のどっちも "Protocol Type" に見えそうだし(もしくはどっちも見えなさそうだし)、やっぱり Existential Type の方がいいか。 (edited)throw したくて禁断の技を使ってしまった・・・。 extension Array: Error where Element: Error {}Set かもだけど、 Hashable にしないといけないので。let aToZ: ClosedRange<Unicode.Scalar> = "A" ... "Z" for c in aToZ { print(c) } ↓みたいな extension 書いた。これって標準で付いてたらダメ? extension Unicode.Scalar: Strideable { public func distance(to other: Unicode.Scalar) -> Int { Int(other.value) - Int(self.value) } public func advanced(by n: Int) -> Unicode.Scalar { Unicode.Scalar(UInt32(Int(self.value) + n))! } }ExpressibleByStringLiteral じゃなくて ExpressibleByUnicodeScalarLiteral が付いてるみたい。 https://developer.apple.com/documentation/swift/unicode/scalarStrideable がついてないって話かStrideable が欲しい。Unicode.Scalar.init で nil になるのかな?
Strideable であってもおかしくない気が。("a" ... "z").randomElement()! とかやりたいことは結構あると思うんだけどなぁ。OrderedCharacter とかあればいいのかな・・・。FunctionBuilder 自体は汎用にしておいて、 Buildable に適合した型だけその結果を使って build できるようにしたいってことですか?Buildable 以外にも FunctionBuilder を使えるようにしたいと。_Builder があるから任意の型を生成できるのか。 (edited)Pair<Pair<Pair<C0, C1>, C2>, C3> じゃなくて Pair<Pair<C0, C1>, Pair<C2, C3>> なのには意図があります?struct Foo { func get() -> Int { 42 } var bar: Int { get() } }<stdin>:4:12: error: expected '{' to start getter definition get() ^struct Foo { func get2() -> Int { 42 } var bar: Int { get2() } } なるほど。struct V<K> { func f(_ k: K) {} } struct S { var name: String = "" } V<KeyPath<S, String>>().f(\.name) // OK V<PartialKeyPath<S>>().f(\S.name) // OK V<PartialKeyPath<S>>().f(\.name) // NG (edited)<stdin>:9:24: error: type of expression is ambiguous without more context V<PartialKeyPath<S>>().f(\.name) // NG ~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~ (edited)V<PartialKeyPath<S>>().f(\S.name) ならいけるっぽい?Key = PartialKeyPath<Props> ってやったらKeyPath<Props, String> だと、 Stringじゃないプロパティが収納できないから駄目。KeyPath<Props, T> mutating func notEmpty(for key: Key, value: String) -> Bool { if !value.isEmpty { return true } addFailure(for: key, .empty) return false }struct Validator<T> { typealias Key = PartialKeyPath<T> mutating func notEmpty<X>(for key: KeyPath<T, X> , _ value: String) -> Bool { ... } var validator = Validator<Props>() _ = validator.notEmpty(for: \.name, props.name)<X> ださい・・・KeyPath<T, X> から PartialKeyPath<T> への変換は暗黙変換だからextension Validator where Key == PartialKeyPath<T> { // ここに生やす } でいけそうやな<T> 書けなくない?T にしばる意味がないValidator<Key: Hashable> だったのだ。\.name って書けなくなる。 (edited) if validator.failures[\.password]?.isEmpty, validator.failures[\.passwordConfirm]?.isEmpty { }PartialKeyPath が見えてるから・・・ 辞書直接さらさずにこれも <X> つけたアクセサ作ればごまかせるけどwextension Validator { subscript<X>(failure: KeyPath<T, X>) -> } ざっくりこんな感じかvalidator[\.name] が収集されたエラーであることが自明でないからAPIとして微妙だな〜func failure<X>(key: KeyPath<X, T>) -> [Failure] かなあ if validator.failures(for: \.password).isEmpty, validator.failures(for: \.passwordConfirm).isEmpty { }subscript(dynamicMember:) とかは?validator.name で nameのエラーが取れるようになるのかなvalidator.failures.name とかはできそうですねvalidator.name.notEmpty(props.name) var validator = Validator(target: props) if validator.notEmpty(for: \.password) { _ = validator.minLength( for: \.password, length: setting.passwordMinLength ) } _ = validator.notEmpty(for: \.passwordConfirm) if validator.failures(for: \.password).isEmpty, validator.failures(for: \.passwordConfirm).isEmpty { _ = validator.checkConfirm(for: \.passwordConfirm, original: \.password) }async/await 入ったら標準ライブラリに Future も入るのかな? Proposal で触れられてるけど。そしたら、標準ライブラリと Combine と SwiftNIO で Future が乱立・・・。throw に対する Result 、 async に対する Future とすると、標準ライブラリでは Future は Failure を持たないという設計も考えられる。Future<Value, Failure: Error> にしてしまうと、今後第三のモナドに対する throws/try, async/await 相当の構文が導入されたときにモメそう。 (edited)async throws な関数をラップすることを考えると Future に Failure がないと厳しいよなぁ・・・。let a = Future { try await foo() } let b = Future { try await bar() } let c = try await a.get() + b.get()func next() async で扱えそうasync/await で generator 作る例を Joe Groff が昔書いてたはず。let a = Future { await Result { try foo() } } let b = Future { await Result { try bar() } } let c = try await a.get().get() + b.get().get() throws-rethrowsと同じように、async-reasyncがあれば、↑のように書けるはず。let a = Future { await Result { try await foo() } } let b = Future { await Result { try await bar() } } let c = try await a.get().get() + b.get().get() って まったく同じこと書いてたw (edited)foo や bar に await がいるはず。reasync されて Future の方でさらに await が必要。Future<Result<T, E>> に対して、 func get() async throws E -> T な extension がほしい。get().get() が get() でよくなる。 (edited)async/await 導入されるなら、 Future が同時に導入されないのはきついので、 Parametrized extension はそれまでに入らなさそうな気がするし、 Failure 入れられちゃいそうな気がする・・・。FutureResult 型が導入されればいいのかな。Future が乱立するか、 Combine.Future に対する extension ができるかかな。NIO.EventLoopFuture は EventLoop の制御が入ってるんでちょっと別ですねCombine.Future はどうなんだろう。Failure == Never のときにはasyncだけの振る舞いをもってれば、十分じゃないです?import Combine extension Future where Failure == Error { init(execute: () async throws -> Value) { ... } } (edited)@escaping がいりそうextension Future where Failure == Never { init(execute: () async -> Value) { ... } } 現実的にはこれと↑の2つでget() async throws -> Output か。Never のときは get() async -> OutputResult のが。protocol Single: Publisher { ... } extension Future: Single { ... } extension Publishers.Map: Single where Upstream: Single { ... }async で取り出せる get がないと辛いし、やっぱ専用の標準 Future ほしそう。Future なしで async/await 入って、オレオレ Future 乱立がありそうだな・・・。Future が Failure を持たなくても、 extension<T> Future where Value == Result<T> { init(execute: @escaping () async throws -> T) { ... } } があれば良い?Result じゃなくて Optional だったけど。a: Future<String, Error> と b: Future<Result<String>, Never は (edited)a.flatMap { Future.failure(err) }.map { print("出ない") }
b.map { Result.failure(err) }.map { print("出る") } このへんが違うから。 (edited)do { let a = try await foo() } catch { ... } do { let b: Result<String, Error> = await bar() } catch { ... } ↑この2つの違いに相当する (edited)Future<Result<T, E>> を Future<T ,E> の気分で使いたいと考えたら、基本的にそういう挙動をするようにすればいいんじゃないのかなぁ。foo.map { a: Result<T, E> in ... } foo.result.map { a: T in ... } こういう感じの書き方ができるとlet b: Result<String, Error> = await Result { try await bar() }foo.map(who: .future) { a: Result<T, E> in ... } foo.map(who: .result) { a: T in ... }async と throws をちゃんと区別してくれたら、 Future は Future<T, E> でいい気もします・・・。Future や Result は主役ではなくて、 async/await や throws/try では解決できないコーナーケースをハンドリングするためのヘルパーなので。reasync がついてる。init(catching body: () throws -> Success) ↑の Result.init が↓に変わる。 init(catching body: () async throws -> Success) reasyncinit は async 書けると思ってるんだけどどうなんだろう?Promise を基本として async/await を考えた場合、Promise を返せないから async にできないけど、Promise や Future に基づかずに async/await を導入する場合、async になれる。async 付いてるのとは挙動は違うけど(待たずに返るので)。 (edited)async コンストラクタができる言語ってあるのかな?init(bigEndian:) と .bigEndian って挙動同じじゃない? https://developer.apple.com/documentation/swift/uint64/1539824-init
https://developer.apple.com/documentation/swift/uint64/1538836-bigendianlet a: UInt64 = 1 print(a.bigEndian) print(UInt64(bigEndian: a))72057594037927936 72057594037927936.endianSwapped などにはしないほうが良いです.bigEndian と .littleEndian の話じゃない? (edited)let a: UInt64 = 1 print(a.bigEndian) // aをLEだと思ってそのBE表現を得ているコード print(UInt64(bigEndian: a)) // aをBEだと思ってそのLE表現を得ているコード // ↑この2つが並んでるのは `a` の解釈が矛盾してるのでおかしい.littleEndian は何もしない関数になるけど.bigEndian が何もしない関数で、 .littleEngian がスワップする関数に切り替わりますね。.endianSwapped は .bigEndian と同じじゃなくて、常にひっくり返すって意味やんね?.bigEndian と .littleEndian の二つは必要。init(bigEndian:) と init(littleEndian:) はそれぞれ .bigEndian, .littleEndian と同じ挙動だから、コードの意図の表明以上の意味はないよね?という疑問。extension UInt64 { var bigEndian: UInt64 { UInt64(bigEndian: self) } } でも構わないわけだ。 @inlinable public var bigEndian: Self { #if _endian(big) return self #else return byteSwapped #endif }_endian
#available(*, unavailable) があるのに。let expectation = XCTestExpectation() var cancellables: [AnyCancellable] = [] observableObject.objectWillChange.sink { _ in expectation.fulfill() }.store(in: &cancellables) wait(for: [expectation], timeout: 3.0) みたいなコード書いてたけど、最適化を有効にしたら(おそらく)スコープの途中で cancellables が片付けられてしまって observableObject が発火しなくなってしまった。cancel を呼び出すことで解放されなくなりました。cancel を呼びやすいように元々 store をなくして戻り値で受けてたんですが、 cancel を消しても(未使用警告は出ますが)購読解除はされませんでした。store に戻した上でcancellables.forEach { $0.cancel() }store で最適化されるなら戻り値で受けた場合も最適化され得るものとして、末尾 cancel するのが良さそうに思います。store のときの挙動が最適化のバグの可能性もあると思います。withExtendedLifetimeを使うのが正しそうvar cancellables: [AnyCancellable] = [] observableObject.objectWillChange.sink { _ in expectation.fulfill() }.store(in: &cancellables) このinoutに渡した例だと何もでない、ですよね?wait(for: [expectation は要するにPromiseだからAsync/Await的な書き方にできそうだな。func XCTAsync<Context>(_ context: Context, timeout: TimeInterval = 3.0, _ body: (inout Context, () -> Void) -> Void) { var context = context let expectation = XCTestExpectation() withExtendedLifetime(context) { body(&context, expectation.fulfill) wait(for: [expectation], timeout: timeout) } } (edited)> GET /builds/swift-5.2.1-release/xcode/swift-5.2.1-RELEASE/swift-5.2.1-RELEASE-osx-symbols.pkg HTTP/1.1 > Host: swift.org > User-Agent: curl/7.64.1 > Accept: */* > < HTTP/1.1 200 OK < Connection: close < Proxy-Connection: close < Via: HTTP/1.1 localhost.localdomain (IBM-PROXY-WTE) < Date: Thu, 17 Sep 2020 05:51:35 GMT < Server: Apache < X-Frame-Options: SAMEORIGIN < Strict-Transport-Security: max-age=15768000;includeSubDomains < Last-Modified: Mon, 30 Mar 2020 11:10:20 GMT < Accept-Ranges: bytes < Content-Length: 3305608957 < Content-Type: application/vnd.apple.installer+xml# whois.ripe.net inetnum: 169.47.73.0 - 169.47.73.31 netname: NETBLK-SOFTLAYER-RIPE-CUST-MS43377-RIPE descr: IBM - Open Technology and Cloud Performance.png を付けたら画像が返るようになっていて、それをOGPのURLにしたHTMLを返している。pod try 的なパッケージをサクッと試せる環境がオンラインで作れると嬉しそうですねswift run すると30個くらいのファイルがコンパイルされたりするのがよくわからない。Content protocol ですね、あれは、 Codable + ContentType です。application/json とか。extension Optional: Content where Wrapped == その型 { ... } かな?encode と init(from decoder) は手書きになるはずsingleValueContainer で出し入れすればいいけど (edited)extension Dictionary: Content, ResponseEncodable, RequestDecodable where Key == String, Value: Content { public static var defaultContentType: HTTPMediaType { return .json } }extension Content { public static var defaultContentType: HTTPMediaType { return .json } ↑これ自動で入らないのかな・・・protocol P { func p() -> Int } struct S<T> {} extension P { func p() -> Int { 1 } } extension S : P where T == Int {}<script> const persons = [ { name: 'Alice' }, { name: 'Bob'}, { name: 'Carol' } ]; </script> <main> {#each persons as p}
<div>{p.name}</div>
{/each}
</main>
<style>
</style>JSValueConstructible という名前にしているんですが、JS value to Swift value なのかSwift value to JS valueなのかわかりにくくてリネームしたい。ExpressibleByXXX っていう案も出たんですが、標準ライブラリ内だとリテラル絡みでしか使われていないのでどうなのかな、と。 (edited)CustomStringConvertible とかを考えるとConvertibleは Self -> Valueなのかなーと思って今の使い方になってますねBridgable も ObjectiveCBridgeable を見るとSelf -> Value と Value -> Selfのペアになっていて微妙にマッチしないextension Bool: SwiftTypeTransformable ってみたときに違和感がある気がするextension Bool: JSValueTransformable こっちの方がわかる。とすると元の名前でも良さそうだけど。extension Bool: JSValueConvertible extension Bool: JSValueBridgeable これは明らかにto JSValueに見える。
SwiftConvertibleはSwift Type側につけるともう意味不明。だから却下でいいかな。extension Bool: ConstructibleFromJSValue わかりやすい。自然。ConstructibleFromJSValue かなぁextension Bool: ExpressibleByJSValue なんか使い方が違うっぽく見えるんですよね。リテラルを変換するやつに引きずられて。XXXConvertible: Self -> Target
- XXXBrigable: Self -> Target & Target -> Self
- ExpressibleByXXX: Literal -> Selfextension Account: ConstructibleFromJSValue みたいな自分で作ったそこそこの規模のStructに実装するとかもある? (edited)extension Bool: InitializableByJSValue {}Self を返す static func は init と等価だと思いますし、 init の方が Swifty な気もします。init(from:) を持つ Decodable ?XxxableFromJSValue は良いように思います。 Xxx に何を入れるか。ConvertibleFromJSValue でもいいのでは?From が入ればニュアンス変わるし。JSValueConvertible と ConvertibleFromJSValue があっても混乱しなさそう(する?)。ConvertibleToJSValue と ConvertibleFromJSValue にすると対応が取れてきれいな気がするけど、悩ましいなDecodable はインターフェース的には近いけど意味的にはもう少し小さい粒度の値の変換だからdecodeは微妙にマッチしないかなぁtrait From<T> とtrait Into<T> が用意されてて羨ましいな (edited)From と Into のドキュメントみてみたんですがFrom trait in crate std.ConvertibleFromJSValue かなConvertibleFromJS ConvertibleToJS かなあ〜Decodable は意味は違うけど Xxxable という形式の名前にするのがやはり良さそうという意味でした。で、今考えている init(from:) が( decode ではなく)何かと言うとやっぱり convert だよなと。そうすると ConvertibleFromJSValue かなと。 (edited)XxxConvertible は to なので、 from であることも明示するには ConvertibleFromXxx かなと。 (edited)ConvertibleToJSValue と ConvertibleFromJSValue がわかりやすそうに思います。Custom がまず謎だし。Xxxable 前置詞 名詞」自体は ExpressibleByStringLiteral とかでもあるし、いい気がします。_ObjectiveCBridgeable は両方向合わせたやつなんだな func _bridgeToObjectiveC() -> _ObjectiveCType と
static func _forceBridgeFromObjectiveC(
_ source: _ObjectiveCType,
result: inout Self?
)trait From っぽいJSValue -> Self は ConstructibleFromJSValue or ConvertibleFromJSValue のどちらかかなと思ってるですが、次の問題として、この場合にSelf -> JSValue をstdlibのXxxConvertibleに寄せるか FromJSValueと対応をとって ConvertibleToJSValue にするか。 (edited)CustomPlaygroundDisplayConvertible
LosslessStringConvertible
CustomDebugStringConvertibleLossless が付くことからもpublic protocol LosslessStringConvertible: CustomStringConvertible {
init?(_ description: String)
}RawRepresentable where RawValue == String っぽいGet<FieldType>()AndroidJavaObject が書けるよ。AndroidJavaObject を指定するのは駄目java.lang.Object に対応してるってこと。int とか boolean は Object ではないので。Representer, Constructorがあっての*Representable,*ConstructibleCodingUserInfoKey.init?(rawValue: String) なんですけどCodingUserInfoKey.init(rawValue: String)
のほうが望ましくないですか?init? じゃなくて init であっても、 RawRepresentable にはconformできます。init? で conform できなかった事による名残じゃないかと予想してるんだけど--privileged を付与しないといけないとかあって危険そうでやめちゃったんですが、特に問題ない感じですか? (edited)/var/run/docker.sock 触れる = それがあるなら --privileged な docker コンテナも作れるのでむしろ DinD のほうがちょっと安全…?Dockerfile内で外向けアプリを実行する前にUSERでアカウントを変更した方が良いです。throws はより軽量だと思いますし、また、例外を throw するのは Either / Result に対する do 記法だという立場からすると、 treat が例外を throw するのと結果を return するのは同じことだとも言えます。can_treat を使う方式だと、チェック忘れを静的に検査できず treat が実行時エラーを起こす可能性を排除できません。Iterator が next で throw して分岐するか、 hasNext でチェックするまたは next が Optional を返すかという話が載っていて後者が望ましいとあるんですけど、 Optional を Result の一種だと考えると、 throw するか Optional を return するのは同じことだとも言えます。 (edited)treat の戻り値の型が Void だったときに、 throws なら分岐を強制できるけど、 Bool か二値 enum だと警告止まりというのはどうでしょう?var a: ArraySlice<Int> = []
for i in 0 ..< 100 {
a.append(i)
print(a.capacity)
}1
3
3
7
7
7
7
17
17
17
17
17
17
17
17
17
17
35
35
35
35
35
35
35
35
35
35
35
35
35
35
35
35
35
35
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
71
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143
143var a: ArraySlice<Int> = []
for i in 0 ..< 100 {
a.append(i)
print(a.capacity)
_ = a.popFirst()
}1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1capacity を超えそうのなったときに前に詰めてる?var a: ArraySlice<Int> = []
a.reserveCapacity(10)
for i in 0 ..< 20 {
a.append(i)
print(a.capacity)
_ = a.popFirst()
}11
10
9
8
7
6
5
4
3
2
1
1
1
1
1
1
1
1
1
1capacity からバッファのサイズはわからないな。Array でもそうかと。 < 既存部分 (edited)append と popFirst を繰り返した場合、 endIndex が capacity を超えたときにどうなると思う?前に詰める? N 倍のバッファを確保して index に基づいた場所に格納される?capacity からわかるかと思ったけど、この capacity の挙動だと実装みないとわからないかな・・・。ArraySlice をキューとして使っていたとすると大きなオフセットになることはありえそう。a ... b で b == a - 1 のときに、実行時エラーじゃなくて空の ClosedRange になってほしい・・・。a ..< b だと空の Range 作れるんですよね。print(Array(0 ..< 0))print(Array(1 ... 0))Fatal error: Can't form Range with upperBound < lowerBound: file Swift/ClosedRange.swift, line 335
Current stack trace:
0 libswiftCore.so 0x00007f0b11e99d50 swift_reportError + 50
1 libswiftCore.so 0x00007f0b11f0d0c0 _swift_stdlib_reportFatalErrorInFile + 115
2 libswiftCore.so 0x00007f0b11bf27de <unavailable> + 1398750
3 libswiftCore.so 0x00007f0b11bf2337 <unavailable> + 1397559
4 libswiftCore.so 0x00007f0b11bf2013 <unavailable> + 1396755
5 libswiftCore.so 0x00007f0b11bf1a80 _assertionFailure(_:_:file:line:flags:) + 511
7 swift 0x00000000005b4501 <unavailable> + 1787137
8 swift 0x00000000005a1d04 <unavailable> + 1711364
9 swift 0x0000000000587e88 <unavailable> + 1605256
10 swift 0x000000000057b322 <unavailable> + 1553186
11 swift 0x00000000005780ef <unavailable> + 1540335
12 swift 0x0000000000501c2c <unavailable> + 1055788
13 libc.so.6 0x00007f0b13f68740 __libc_start_main + 240
14 swift 0x00000000005017a9 <unavailable> + 1054633
Stack dump:
0. Program arguments: /usr/bin/swift -frontend -interpret - -disable-objc-interop -I /Libraries/.build/x86_64-unknown-linux-gnu/debug -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/CSwiftBacktrace/include -I /Libraries/.build/checkouts/SwiftBacktrace/Sources/Clibunwind/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOHTTPParser/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOSHA1/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOAtomics/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIOWindows/include -I /Libraries/.build/checkouts/swift-nio/Sources/CNIODarwin/include -I print(Array(0 ... 0)) /// Because a closed range cannot represent an empty range, this property is
/// always `false`.
@inlinable
public var isEmpty: Bool {
return false
}
なんで、無理ですねr が 0 だとクラッシュしてしまいます。
func npr(_ n: Int, _ r: Int) -> Int {
(n - r + 1 ... n).reduce(into: 1) { $0 *= $1 }
}..< の右の n + 1 が不格好なんですよね・・・。
func npr(_ n: Int, _ r: Int) -> Int {
(n - r + 1 ..< n + 1).reduce(into: 1) { $0 *= $1 }
}... 使うと実行時エラーを踏みまくるので、 ..< ばかり使うようにしています。lowerBound == upperBound + 1 の場合だけ空だと、実用上はちょうど良いように思います。ただ、表現として微妙なのはわかります。Strideable じゃない場合との整合性を考えると微妙ですね・・・。 (edited)!= を≠にするのはあるけど否定のビックリをみやすくしてくれるのはなかった気がする。error: cannot find operator '!!!' In scope カスタムオペレーターの弊害とはいえ、悲しい。≠ を表したくて、 縦棒っぽい記号が欲しかっただけと思ってた !=+= と + の関係を考えると、 != から ! が取り出せる¬ だextension Bool { var isFalse: Bool { !self } }! はないっぽい?protocol 作るときに、型ではなく制約としての利用を前提とするなら、基本的に FooProtocol の命名の方が良い気がするんですがどうでしょう?
protocol Foo {}
struct Bar<???: Foo> {} // ??? に何と付ける?
protocol FooProtocol {}
struct Bar<Foo: FooProtocol> {} // 型パラメータ名を Foo にすれば良い (edited)Numeric みたいな汎用的なプロトコルの場合は struct Bar<Length: Numeric> みたいに命名できるけど、もっと用途の幅が狭いものの場合。 (edited)var value: Value とか。VideoSource というプロトコルを作ってたんだけど、
struct PlayerView<VideoSource: VideoSourceProtocol>: View { ... }
にしたくなった。VideoSourceTypeType suffix 結構使うな。 (edited)V: VideoSource で良い気もするんだけど主流じゃなさそうだ。associatedtype や型パラメータって何度も繰り返し使われるから、 associatedtype Iterator: IteratorProtocol 的にプロトコル名を長くした方がよくないですか?associatedtype はそうかも。 (edited)IteratorProtocol があるからもう天下り的にいいかなと・・・。I prefix は賢い気がする。typename キーワードでそういう事をする場面があってstruct Bar<Foo: MyModule.Foo> {}struct Bar<Foo: MyModule.Foo> {} /usr/lib/swift/libswift_Concurrency.dylibが絶対パスでリンクされて、SIP有効だとDYLD_LIBRARY_PATHも渡せないから、
DYLD_LIBRARY_PATH=… swift runはダメだけど、DYLD_LIBRARY_PATH=… .build/x86_64-apple-macosx/debug/ConcurrencyExampleとして直接実行するのはイケた。SIP関係ないのかな?DYLD_LIBRARY_PATHを渡さないようにしてるのかな?
何か条件があるぽい。
$ env DYLD_LIBRARY_PATH=hoge /usr/bin/python3 -c "import os;print('DYLD_LIBRARY_PATH' in os.environ)"
False
$ env DYLD_LIBRARY_PATH=hoge /usr/local/bin/python3 -c "import os;print('DYLD_LIBRARY_PATH' in os.environ)"
True (edited)PATHに$HOME/Library/Developer/Toolchains以下にインストールしたSwiftツールチェインの/usr/binを通してDYLD_LIBRARY_PATH=… swift runしてもダメなんですよね。なので「インストーラで入れた」が条件なのかな?と。$ xattr -rv ~/Library/Developer/Toolchains/|grep -v -E "com.apple.(cs.Code(Directory|Requirements|Requirements-1|Signature)|metadata:com_apple_backup_excludeItem|FinderInfo)"|wc -l
0 (edited).build/x86_64-apple-macosx/debug/ConcurrencyExampleをDeveloper ID Applicationで署名してみましたが、DYLD_LIBRARY_PATHは通りました。
$ swiftnightly build
[1/1] Planning build
[3/3] Linking ConcurrencyExample
* Build Completed!
$ codesign -s "Developer ID Application: Norio Nomura (PK9GMQ772L)" .build/debug/ConcurrencyExample
$ codesign -vv .build/debug/ConcurrencyExample
.build/debug/ConcurrencyExample: valid on disk
.build/debug/ConcurrencyExample: satisfies its Designated Requirement
$ DYLD_LIBRARY_PATH=~/Library/Developer/Toolchains/swift-DEVELOPMENT-SNAPSHOT-2021-01-09-a.xctoolchain/usr/lib/swift/macosx .build/debug/ConcurrencyExample
task started
{
"uuid": "32cf6d86-bb2d-4089-8262-9ecfcf9d7418"
}
end of mainmealHandle と () の間に .get が抜けてる?
func eat(mealHandle: Task.Handle<Meal, Error>) {
let meal = try await mealHandle()
meal.eat() // yum
}
https://github.com/DougGregor/swift-evolution/blob/structured-concurrency/proposals/nnnn-structured-concurrency.mdlet a: [String?:String] = ["Foo":"Bar"]
let b = a as [AnyHashable:String]
print(b["Foo"] == "Bar")
print(b["Foo" as String?] == "Bar")"foo" と .some("foo") がAnyHashable としてみると違う値なのか?print(AnyHashable("foo") == AnyHashable(Optional<String>("foo"))) (edited)print(AnyHashable("foo") == AnyHashable(Optional<String>("foo")))let str = "foo"
let ostr: String? = str
let hstr: AnyHashable = ostr as AnyHashable
print(hstr == AnyHashable(str))
print(hstr == AnyHashable(ostr)) (edited)let str = "foo"
let ostr: String? = str
let tempAny: Any = ostr
let hstr: AnyHashable = tempAny as! AnyHashable
print(hstr == AnyHashable(str))
print(hstr == AnyHashable(ostr))false
truestderr:<stdin>:3:20: warning: expression implicitly coerced from 'String?' to 'Any'
let tempAny: Any = ostr
^~~~
<stdin>:3:20: note: provide a default value to avoid this warning
let tempAny: Any = ostr
^~~~
?? <#default value#>
<stdin>:3:20: note: force-unwrap the value to avoid this warning
let tempAny: Any = ostr
^~~~
!
<stdin>:3:20: note: explicitly cast to 'Any' with 'as Any' to silence this warning
let tempAny: Any = ostr
^~~~
as Anytrue
falsestderr:<stdin>:3:20: warning: expression implicitly coerced from 'String?' to 'Any'
let tempAny: Any = ostr
^~~~
<stdin>:3:20: note: provide a default value to avoid this warning
let tempAny: Any = ostr
^~~~
?? <#default value#>
<stdin>:3:20: note: force-unwrap the value to avoid this warning
let tempAny: Any = ostr
^~~~
!
<stdin>:3:20: note: explicitly cast to 'Any' with 'as Any' to silence this warning
let tempAny: Any = ostr
^~~~
as AnyT?? における .some(.none) と .none の区別とかもあるしなあfunc toAny<X>(_ x: X) -> Any { x as Any }
let s = "foo"
let os = Optional(s)
let a1 = toAny(s) as! AnyHashable
let a2 = toAny(os) as! AnyHashable
print(a1 == a2) (edited)func toAny<X>(_ x: X) -> Any { x as Any }
let s = "foo"
let os = Optional(s)
let a1 = toAny(s) as! AnyHashable
let a2 = toAny(os) as! AnyHashable
print(a1.hashValue, a2.hashValue, a1 == a2) (edited)let a = Optional.some(1)
let b = 1
print(a.hashValue)
print(b.hashValue)5998755465171700993
32460834557614620814555010388509318116 7560537639487603476 falselet s = "s"
let os=Optional(s)
print(type(of: s), type(of: os), type(of: s as Any), type(of: os as Any)) (edited)let s = "s"
let os = Optional(s)
print(type(of: s), type(of: os), type(of: s as AnyHashable), type(of: os as AnyHashable)) (edited)func toAH<X>(_ x: X) -> AnyHashable { x as! AnyHashable }
let s = "foo"
let os = Optional(s)
print(type(of: toAH(s)), type(of: toAH(os)), type(of: toAH(s) as Any), type(of: toAH(os) as Any)) (edited)print("s" as AnyHashable as? String)Optional("s")stderr:<stdin>:1:7: warning: expression implicitly coerced from 'String?' to 'Any'
print("s" as AnyHashable as? String)
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<stdin>:1:26: note: provide a default value to avoid this warning
print("s" as AnyHashable as? String)
~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
?? <#default value#>
<stdin>:1:26: note: force-unwrap the value to avoid this warning
print("s" as AnyHashable as? String)
~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
!
<stdin>:1:26: note: explicitly cast to 'Any' with 'as Any' to silence this warning
print("s" as AnyHashable as? String)
~~~~~~~~~~~~~~~~~~~^~~~~~~~~~
as AnyAnyHashable AnyHashable AnyHashable AnyHashablefunc toAH<X>(_ x: X) -> AnyHashable { x as! AnyHashable }
let s = "foo"
let os = Optional(s)
let a1 = toAH(s)
let a2 = toAH(os)
print(a1 == a2, a1.hashValue, a2.hashValue)false 7411312793998186712 -1838519281677881482true -7218179261913021143 -7218179261913021143String? を動的に AnyHashable にするときに String? を包んだものとしてキャストしていてString をキャストしたものになるfunc toAH<X>(_ x: X) -> AnyHashable { x as! AnyHashable }
let s = "foo"
let os = Optional(s)
let a1 = toAH(s)
let a2 = toAH(os)
let d1: [AnyHashable: Int] = [s: 1]
let d2: [AnyHashable: Int] = [a1: 1]
print(d1[s] ?? 99, d1[os] ?? 99, d1[a1] ?? 99, d1[a2] ?? 99)
print(d2[s] ?? 99, d2[os] ?? 99, d2[a1] ?? 99, d2[a2] ?? 99) (edited)d1[os] のときにやってるのは静的な方か?T? as AnyHashable のとき、アンラップしなかった方のAH が生成されるんだねswift-5.0.3-RELEASEは起動できるけど、それ以降の5.1.5, 5.2.5, 5.3.3リリースおよび5.4, mainスナップショット全部起動出来ない。switch rpcMessageType {
case .playAnimation:
<#code#>
case .completeTask:
<#code#>
case .syncSettings:
<#code#>
case .setInfected:
<#code#>
...
今はこんな感じに生成されるけど、<#code#> のところbreakがいい、気がする。code に行っちゃうのが不便なときはあるinfix operator ..<?: RangeFormationPrecedence
func ..<?<T>(lhs: T, rhs: T) -> Range<T>? where T: Comparable {
guard lhs <= rhs else { return nil }
return lhs ..< rhs
}
infix operator ...?: RangeFormationPrecedence
func ...?<T>(lhs: T, rhs: T) -> ClosedRange<T>? where T: Comparable {
guard lhs <= rhs else { return nil }
return lhs ... rhs
}Scheduling for next Monday. されとる (edited)implicit が導入されると黒魔術が使えて嬉しいsuffix(while:) ってなんでないんですっけ?普通にほしい気が。let a: Int
if Bool.random() {
a = 2
} else {
a = 3
}
print(a)let a: Int?
if Bool.random() {
a = 2
} else {
a = nil
}
print(a)nilstderr:<stdin>:7:7: warning: expression implicitly coerced from 'Int?' to 'Any'
print(a)
^
<stdin>:7:7: note: provide a default value to avoid this warning
print(a)
^
?? <#default value#>
<stdin>:7:7: note: force-unwrap the value to avoid this warning
print(a)
^
!
<stdin>:7:7: note: explicitly cast to 'Any' with 'as Any' to silence this warning
print(a)
^
as Anyif let でシャドーイングされてた・・・。すみません。subscript(index: Int) が生えててもいい気も。さすがに subscript は勘違いしそうかもしれないけど。first が Sequence に生えてても良さそう?first(where:) は一応最悪O(N)では (edited)extension Sequence {
var first: Element? {
var iterator = makeIterator()
return iterator.next()
}
}let a: [Int] = [2, 3, 5]
let i: [Int].Iterator = a.makeIterator()<stdin>:2:13: error: consecutive statements on a line must be separated by ';'
let i: [Int].Iterator = a.makeIterator()
^
;
<stdin>:2:14: error: member 'Iterator' in 'IndexingIterator<[Int]>' produces result of type 'IndexingIterator<[Int]>.Iterator.Type' (aka 'IndexingIterator<Array<Int>>.Type'), but context expects 'IndexingIterator<[Int]>'
let i: [Int].Iterator = a.makeIterator()
^let a: [Int] = [2, 3, 5]
let i: Array<Int>.Iterator = a.makeIterator(). でつなぐメンバータイプは文法上 type identifier のみに設定されているのです。let a = [Int].Element()
print(a)
ただこれは動いちゃうのです。なぜならこれは文法上 type じゃなくて expression としてパースされるから。let s: String? = .none
let t: String?? = s
let u: String?? = .none
let x = (s as AnyHashable).hashValue
let y = (t as AnyHashable).hashValue
let z = (u as AnyHashable).hashValue
print(s == t, x == y)
print(s == u, x == z)true false
false truea == b -> a.hashValue == b.hashValueのはずですが、
ここでは型が一致していないので、xとy,zを並べて良いものか怪しい気がします。s == tとs==uは暗黙的にOptional`に包まれるのもありますし。T ∈ Hashable, ∀a,b ∈ T, a == b -> a.hashValue == b.hashValue
定義がこんな感じだとすると、String?とString??で型が一致していない場合は前提が崩れるのでhashValueについては何も言えないはずです。var s1 = "Foo"
var s2 = Optional("Foo")
print(s1.hashValue, s2.hashValue)
print((s1 as AnyHashable).hashValue, (s2 as AnyHashable).hashValue)
print((s1 as! AnyHashable).hashValue, (s2 as! AnyHashable).hashValue)-4610515456940335649 5550570105904624955
-4610515456940335649 5550570105904624955
-4610515456940335649 -4610515456940335649stderr:<stdin>:5:11: warning: forced cast from 'String' to 'AnyHashable' always succeeds; did you mean to use 'as'?
print((s1 as! AnyHashable).hashValue, (s2 as! AnyHashable).hashValue)
^~~
as
<stdin>:5:43: warning: forced cast from 'String?' to 'AnyHashable' always succeeds; did you mean to use 'as'?
print((s1 as! AnyHashable).hashValue, (s2 as! AnyHashable).hashValue)
^~~
as.swiftinterface ですね。.swiftinterface ですね。 .swiftmodule は .swiftinteface のバイナリ表現(キャッシュ)で clang でいうところの .pcm (edited).swiftinterface は後方互換性あるけど、 .swiftmodule は生成したコンパイラバージョンでしか読めない。で、配布しないモジュールは後方互換性を確保する必要が無いので、.swiftinterface を出す必要がないので出してないノだと思います。.swiftmodule を入れられて、それが import できる、つまり .swiftinterface の代わりに(コンパイラのバージョンが一致していれば) .swiftmodule を使うことができる状態になっている。.swiftinterface と .swiftmodule のどっちが「正」かっていうのは議論あるかも。
https://forums.swift.org/t/explicit-module-builds-the-new-swift-driver-and-swiftpm/36990 ここでは "there are four forms of module"protocol P {}
struct S: P {}
func check(_ maybeS: S?) {
print("maybeS = \(maybeS)")
print("maybeS is P = \(maybeS is P)")
print("maybeS as Any is P = \(maybeS as Any is P)")
print("------------------------------------------")
}
check(S())
check(nil)maybeS = Optional(main.S())
maybeS is P = true
maybeS as Any is P = true
------------------------------------------
maybeS = nil
maybeS is P = false
maybeS as Any is P = false
------------------------------------------stderr:<stdin>:6:23: warning: string interpolation produces a debug description for an optional value; did you mean to make this explicit?
print("maybeS = \(maybeS)")
^~~~~~
<stdin>:6:23: note: use 'String(describing:)' to silence this warning
print("maybeS = \(maybeS)")
^~~~~~
String(describing: )
<stdin>:6:23: note: provide a default value to avoid this warning
print("maybeS = \(maybeS)")
^~~~~~
?? <#default value#>
<stdin>:7:35: warning: checking a value with optional type 'S?' against dynamic type 'P' succeeds whenever the value is non-nil; did you mean to use '!= nil'?
print("maybeS is P = \(maybeS is P)")
~~~~~~ ^~~~
!= nilmaybeS = Optional(main.S())
maybeS is P = true
maybeS as Any is P = false
------------------------------------------
maybeS = nil
maybeS is P = false
maybeS as Any is P = false
------------------------------------------stderr:<stdin>:6:23: warning: string interpolation produces a debug description for an optional value; did you mean to make this explicit?
print("maybeS = \(maybeS)")
^~~~~~
<stdin>:6:23: note: use 'String(describing:)' to silence this warning
print("maybeS = \(maybeS)")
^~~~~~
String(describing: )
<stdin>:6:23: note: provide a default value to avoid this warning
print("maybeS = \(maybeS)")
^~~~~~
?? <#default value#>
<stdin>:7:35: warning: checking a value with optional type 'S?' against dynamic type 'P' succeeds whenever the value is non-nil; did you mean to use '!= nil'?
print("maybeS is P = \(maybeS is P)")
~~~~~~ ^~~~
!= nilFoundation.Process で /usr/bin/swiftc を実行しようとすると、
2021-06-05 15:20:12.963749+0900 swiftc[99910:13408271] Failed to open macho file at /Applications/Xcode12.5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc for reading: Too many levels of symbolic links/Applications/Xcode12.5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc が
-> swift-frontend にリンクしてるだけで終わりなんですよね。 (edited)man dyld 見たけど多すぎてよくわからなかった・・・Test Case '-[SE0295PolyfillTests.JSONCodingTests test01]' started.
generate: Command-SE0295.gen.swift
2021-06-07 11:16:01.228423+0900 swiftc[77103:15204344] Failed to open macho file at /Applications/Xcode12.5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc for reading: Too many levels of symbolic links
Test Case '-[SE0295PolyfillTests.JSONCodingTests test01]' passed (1.409 seconds).Foundation.Process で /usr/bin/swiftc を実行しようとすると、
2021-06-05 15:20:12.963749+0900 swiftc[99910:13408271] Failed to open macho file at /Applications/Xcode12.5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc for reading: Too many levels of symbolic links Too many levels... の文字列はなかったJSONCodingTests.swift$ cat main.swift
import Foundation
let p = Process()
p.executableURL = URL(fileURLWithPath: "/usr/bin/env")
p.arguments = ["swiftc", "-o", "out", "main.swift"]
try p.run()
p.waitUntilExit()swift test で実行すると再現しないっぽい… テストランナーの問題なのかなswift test のテストランナーは完全に同じっぽいしわけわからんgenerate-xcodeproj は問題なかったLibrary not loaded: @rpath/lib_InternalSwiftSyntaxParser.dylibXcode.app が焼き込まれてるファイルを見つけたTest Case '-[SE0295PolyfillTests.JSONCodingTests test01]' started.
generate: Command-SE0295.gen.swift
2021-06-07 11:42:14.894107+0900 swiftc[77512:15232794] Failed to open macho file at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc for reading: Too many levels of symbolic links2021-06-06 19:44:33.440695-0700 swiftc[12611:1786858] Failed to open macho file at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc for reading: Too many levels of symbolic links (edited)xcodebuild -scheme Example-Package -derivedDataPath build test で試してる2021-06-06 19:47:34.100871-0700 swiftc[12779:1790755] Failed to open macho file at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc for reading: Too many levels of symbolic links
Apple Swift version 5.4 (swiftlang-1205.0.26.9 clang-1205.0.19.55) でますねDYLD_FALLBACK_FRAMEWORK_PATH=/Applications/Xcode-12.5.app/Contents/SharedFrameworks:/Applications/Xcode-12.5.app/Contents/Developer/Platforms/MacOSX.platform/Developer/Library/Frameworks
DYLD_FALLBACK_LIBRARY_PATH=/Applications/Xcode-12.5.app/Contents/Developer/Platforms/MacOSX.platform/Developer/usr/lib
DYLD_FRAMEWORK_PATH=/Users/kateinoigakukun/Library/Developer/Xcode/DerivedData/Example-dcyedciowpcsqebafcorbracmhpk/Build/Products/Debug
DYLD_LIBRARY_PATH=/Users/kateinoigakukun/Library/Developer/Xcode/DerivedData/Example-dcyedciowpcsqebafcorbracmhpk/Build/Products/Debug$ xcodebuild -project SE0295Polyfill.xcodeproj -scheme SE0295Polyfill-Package testTest Case '-[SE0295PolyfillTests.JSONCodingTests test01]' started.
generate: Command-SE0295.gen.swift
2021-06-07 11:57:01.005930+0900 swiftc[78065:15248887] Failed to open macho file at /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc for reading: Too many levels of symbolic links
Test Case '-[SE0295PolyfillTests.JSONCodingTests test01]' passed (2.926 seconds)./Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc を swiftc の代わりに実行するとエラーがでない/usr/bin/swiftc を Xcode から実行することに問題がある...?/usr/bin/*のshimはこのライブラリ経由でxcode-selectとDEVELOPER_DIRを見て実体のパスを解決してexecするんですよね$ ls -al /usr/lib/libxcselect.dylib
ls: /usr/lib/libxcselect.dylib: No such file or directoryxcselect_invoke_xcrun 実行してるだけだなあswiftc -v を lldb swiftc に置き換えてみたNot allowed to attach to process._parse_macho_iterate_slices_parse_macho_iterate_slices_fd がエラーだなぁfstat してるからそれがなんかおかしなことになってしまってる?_parse_macho_iterate_slices の open ですでにダメなのか_parse_macho_iterate_slices にブレイクポイントいれらたら$arg0 ($rdi) をみればパスがわかるはず (edited)let ret = open("/Applications/Xcode-12.5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc", 0x100)
print(ret)
これは-1が返ってくるprint(String(cString: strerror(errno))) するとToo many levels of symbolic linksだ#define O_NOFOLLOW 0x00000100 /* don't follow symlinks */_parse_macho_iterate_slices 呼ばないケースがあるんだと思う syslog$DARWIN_EXTSN(0x3, "Failed to open macho file at %s for reading: %s", r15, strerror(*(int32_t *)__error()));
rax = 0x0;_parse_macho_iterate_slices_fd はMach-Oを検証してる感じかなあ_parse_macho_iterate_slices 呼ばれてない?OS_ACTIVITY_DT_MODE=YES これだ!Test Case '-[SE0295PolyfillTests.JSONCodingTests test01]' started.
generate: Command-SE0295.gen.swift
Test Case '-[SE0295PolyfillTests.JSONCodingTests test01]' passed (1.140 seconds).
Test Case '-[SE0295PolyfillTests.JSONCodingTests test02]' started.
generate: Command-SE0295.gen.swift
Test Case '-[SE0295PolyfillTests.JSONCodingTests test02]' passed (0.935 seconds).
Test Case '-[SE0295PolyfillTests.JSONCodingTests test03]' started.
generate: Command-SE0295.gen.swift
Test Case '-[SE0295PolyfillTests.JSONCodingTests test03]' passed (0.933env OS_ACTIVITY_DT_MODE=1 swiftc がminimum reproです(URLResponse, Data) ?let hogeRes = try await URLSession.shared.data(for: hogeReq)
// いろいろ
let hogeData = hogeRes.0
ってなるのはちょっとダサさがあり…throws なので。let (res, data) = try await URLSession... で受けると良いかも?(data: Data, response: URLResponse) とかになってくれるとうれしいstruct DataTaskResult とかで nominal type でも良い気がするけど(自分はそうラップしている) (edited)async 化されてるんだとしたら、https://github.com/apple/swift-evolution/blob/main/proposals/0297-concurrency-objc.md#asynchronous-completion-handler-methods で議論されなかったのかな。The method itself has a void result type, because all results are delivered by the completion handler block. に引っかかりそう)(_ data: Data?, _ response: URLResponse?, _ error: Error?) -> Void というシンタックスはあるので、引数名乗るようにインポートすることは可能なはずです。(data: Data, response: URLResponse) とかになってくれるとうれしい NS_SWIFT_DISABLE_ASYNC というのが追加されているのでこれがあるやつはasyncに自動変換されないって感じなんですかね。
// 14.5
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion API_AVAILABLE(ios(5.0));
// 15.0
- (void)presentViewController:(UIViewController *)viewControllerToPresent animated: (BOOL)flag completion:(void (^ __nullable)(void))completion NS_SWIFT_DISABLE_ASYNC API_AVAILABLE(ios(5.0));default: fatalError() at then end of it, I have a compiler too slow error. If I put it, I have a Default will never be executed. Best of all, I cannot disable the warning in the package, so I'm left with 4 warnings at all times. Anything I can do?
func readInts() -> [Int] {
return readLine()!.split(separator: " ").map {Int(String($0))!}
}
func main() {
let K = Int(readLine()!)!
if !K.isMultiple(of: 9) {
print(0)
return
}
var dp: [Int] = Array(repeating: 0, count: K+1)
dp[0] = 1
for i in 1...K {
for j in max(0, i-9)..<i {
dp[i] = (dp[i] + dp[j]) % (Int(1e9) + 7)
//print(terminator: "")
}
}
print(dp[K])
}
main()-Ounchecked 付きでコンパイルされます。(追記) Linux です。 (edited)let K = [9].randomElement()!にしてここのSwift-5.2.5君に -Ounchecked で食わせても1にならないreadInts() は使ってなさそうですね。let K = [9].randomElement()!にしてここのSwift-5.2.5君に -Ounchecked で食わせても1にならない -Ouncheckedを外すと起きない。
$ pbpaste
func main() {
let K = Int(readLine()!)!
if !K.isMultiple(of: 9) {
print(0)
return
}
var dp: [Int] = Array(repeating: 0, count: K+1)
dp[0] = 1
for i in 1...K {
for j in max(0, i-9)..<i {
dp[i] = (dp[i] + dp[j]) % (Int(1e9) + 7)
//print(terminator: "")
}
}
print(dp[K])
}
main()
$ pbpaste|docker run -i norionomura/swift:5.2 sh -c 'swiftc -Ounchecked -; echo 9|./main'
1
$ pbpaste|docker run -i norionomura/swift:5.2 sh -c 'swiftc -; echo 9|./main'
256
$ pbpaste|docker run -i norionomura/swift:5.3 sh -c 'swiftc -Ounchecked -; echo 9|./main'
256
$ pbpaste|docker run -i norionomura/swift:5.3 sh -c 'swiftc -; echo 9|./main'
256 (edited)#20 1.569 [2215/2636] Compiling _NumericsShims _NumericsShims.c
#20 1.623 [2216/2637] Compiling _AtomicsShims.c
#20 1.623 [2217/2637] Compiling CSystem shims.c
#20 3.014 [2218/2637] Compiling RealModule AlgebraicField.swift
#20 4.016 [2219/2640] Compiling DequeModule Compatibility.swift
#20 6.883 SIL memory lifetime failure in @$s13ComplexModule0A0V3logyACyxGAEFZ: memory is not initialized, but should
#20 6.883 memory location: %98 = alloc_stack $RealType, let, name "θ" // users: %392, %390, %234, %235, %406, %247, %100
#20 6.883 at instruction: copy_addr %98 to [initialization] %391 : $*RealType // id: %392
#20 6.883
#20 6.883 in function:
#20 6.883 // static Complex.log(_:)
#20 6.883 sil [serialized] [ossa] @$s13ComplexModule0A0V3logyACyxGAEFZ : $@convention(method) <RealType where RealType : Real> (@in_guaranteed Complex<RealType>, @thin Complex<RealType>.Type) -> @out Complex<RealType> {
swift-numericsがこんな感じのエラーでDocker上でだけビルドできないっていうのにずっと悩んでたけど、Dockerに割り当てるリソースを増やしたら解決した。
CIでもちょっと内容は違うけど似たようなところで失敗していてそれは -j 1 を指定したらビルドできるようになった。
SIL memory lifetime failure ってなんだろうってずっと悩んでいた。func foo(completion: @escaping () -> Void) {}
final class C {
var a: Int = 0
func bar() {
foo { [self] in
a += 1
}
}
}func foo(completion: @escaping () -> Void) {}
final class C {
var a: Int = 0
func bar() {
foo { [weak self] in
guard let self = self else { return }
foo { [self] in
a += 1
}
}
}
}<stdin>:8:17: error: reference to property 'a' in closure requires explicit use of 'self' to make capture semantics explicit
a += 1
^
<stdin>:7:20: note: variable other than 'self' captured here under the name 'self' does not enable implicit 'self'
foo { [self] in
^
<stdin>:7:20: warning: capture 'self' was never used
foo { [self] in
^weak self を介すると [self] は使えないのか。preconditionFailure だけど万が一のプロダクションでのクラッシュを避けるために assertionFailure & return してたパターン(このパターン自体に賛否はあるけど)、 async になったら値を返さないといけないので preconditionFailure にするしかない?インスタンス生成が簡単なら適当な値を返して握りつぶすことはできなくはないけど。
func foo(completion: @escaping (Foo) -> Void) {
guard checkState(self.state) else {
assertionFailure()
return
}
...
} (edited)foo() async -> Foo? にしてnilが返ってたらスルーとかにはできそうですね。
本来ありえないケースのためにOptionalにするのはちょっと微妙そうですが。preconditionFailure にするのが正しいんだけど、絶対にクラッシュさせたくないから assertionFailure にしておいて Release ビルドでは握りつぶしたいというテクニックを使っているケースの話ですね。まあ Optional にして呼び出し側で握りつぶす実装になるのかな。気持ち悪いけど。throws でいいケースなら↓は良さそうだな。
assertionFailure()
throw CancellationError()struct APIResponse<Value>: Decodable where Value: Decodable {
var value: Value?
var error: APIResponseError?
func result() -> Result<Value, Error> {
print("result")
switch (value, error) {
case (let value?, nil): return .success(value)
case (nil, let error?): return .failure(error)
case (_, _): return .failure(APIResponseError(code: -1))
}
}
func result<Wrapped>() -> Result<Value, Error> where Value == Wrapped? {
print("result optional")
switch (value, error) {
case (let value?, nil): return .success(value)
case (nil, let error?): return .failure(error)
case (nil, nil): return .success(nil)
case (_, _): return .failure(APIResponseError(code: -1))
}
}
}
struct APIResponseError: Error, Decodable {
var code: Int
}
struct User: Codable {}
let r1: APIResponse<User> = .init(value: nil, error: nil)
print(r1.result())
let r2: APIResponse<User?> = .init(value: nil, error: nil)
print(r2.result())result
failure(main.APIResponseError(code: -1))
result
failure(main.APIResponseError(code: -1))r2 の場合 "result optional" の方が優先度高くならないんですっけ?非ジェネリックとジェネリックだから?result が表示されるか result optional が表示されるか。@_disfavoredOverload の出番か・・・。-debug-constraint みてみたんですが、スコア自体は両方同じで、constraintの数で勝敗が付いたっぽいですねprotocol OptionalProtocol: ExpressibleByNilLiteral {
associatedtype Wrapped
static func some(_ value: Wrapped) -> Self
static var none: Self { get }
}
extension OptionalProtocol {
init(nilLiteral: Void) {
self = .none
}
}
extension Optional: OptionalProtocol {}
struct APIResponse<Value>: Decodable where Value: Decodable {
var value: Value?
var error: APIResponseError?
}
extension APIResponse {
func result() -> Result<Value, Error> {
print("result")
switch (value, error) {
case (let value?, nil): return .success(value)
case (nil, let error?): return .failure(error)
case (_, _): return .failure(APIResponseError(code: -1))
}
}
}
extension APIResponse where Value: OptionalProtocol {
func result() -> Result<Value, Error> {
print("result optional")
switch (value, error) {
case (let value?, nil): return .success(value)
case (nil, let error?): return .failure(error)
case (nil, nil): return .success(nil)
case (_, _): return .failure(APIResponseError(code: -1))
}
}
}
struct APIResponseError: Error, Decodable {
var code: Int
}
struct User: Codable {}
let r1: APIResponse<User> = .init(value: nil, error: nil)
print(r1.result())
let r2: APIResponse<User?> = .init(value: nil, error: nil)
print(r2.result())result
failure(main.APIResponseError(code: -1))
result optional
success(nil)self を shadow しても 暗黙の self は shadow されないのむずいimport Foundation
print(atan2(1.0, 0.0))1.5707963267948966import Foundation
print(atan2(1, 0))<stdin>:2:7: error: ambiguous use of 'atan2'
print(atan2(1, 0))
^
Foundation.atan2:1:13: note: found this candidate
public func atan2(_ lhs: CGFloat, _ rhs: CGFloat) -> CGFloat
^
Glibc.atan2:1:13: note: found this candidate
public func atan2(_ lhs: Float, _ rhs: Float) -> Float
^
Glibc.atan2:1:13: note: found this candidate
public func atan2(_ lhs: Float80, _ rhs: Float80) -> Float80
^
SwiftGlibc.atan2:1:13: note: found this candidate
public func atan2(_ __y: Double, _ __x: Double) -> Double
^1.0 なら ExpressibleByFloatLiteral の優先順位で Double が優先されるけど、 1 だと他の浮動小数点数に対して Double が優先されずに ambiguous になるっぽい。1f とかやらなくていいSwiftでも .0 を明示的に書く意味はちょっとある。 (edited)- http:
paths:
- backend:
serviceName: runner-vnightly-main
servicePort: 80
path: /runner/nightly-main/*
pathType: ImplementationSpecific
- backend:
serviceName: runner-vnightly-55
servicePort: 80
path: /runner/nightly-55/*
pathType: ImplementationSpecific
- backend:
serviceName: runner-vnightly-54
servicePort: 80
path: /runner/nightly-54/*
pathType: ImplementationSpecific
- backend:
serviceName: runner-vnightly-53
servicePort: 80
path: /runner/nightly-53/*
pathType: ImplementationSpecific
- backend:
serviceName: runner-v542
servicePort: 80
path: /runner/5.4.2/*
pathType: ImplementationSpecific
- backend:
serviceName: runner-v541
servicePort: 80
path: /runner/5.4.1/*
こんなルーティングで振り分けています。services:
app:
image: kishikawakatsumi/swift-playground:latest
...
carbonara:
image: petersolopov/carbonara
...
nginx-proxy:
image: nginxproxy/nginx-proxy
...
acme-companion:
image: nginxproxy/acme-companion
...
swift-nightly-main:
image: swiftlang/swift:nightly-main
container_name: swift-nightly-main
swift-nightly-5.5:
image: swiftlang/swift:nightly-5.5
container_name: swift-nightly-5.5
swift-nightly-5.4:
image: swiftlang/swift:nightly-5.4
container_name: swift-nightly-5.4
swift-nightly-5.3:
image: swiftlang/swift:nightly-5.3
container_name: swift-nightly-5.3
swift-5.4.1:
image: kishikawakatsumi/swift:5.4.1
container_name: swift-5.4.1
swift-5.4:
image: kishikawakatsumi/swift:5.4
container_name: swift-5.4
...
こんなdocker-compose.ymlでした。 (edited)private メソッドからだけ呼ばれるメソッド群(処理に名前を付けるだけ)が他のメソッドから可視なのが気持ち悪い。それらを extension にまとめた上で extension private にして、そのメソッドからだけ可視にしたい。data-bs-container っていうオプションを発見してそれでボタンを指定すれば安定するようになりました。actor を考えると、 Fault Isolation の単位が actor であるべきかは微妙な気がするんですよね。別の仕組みとして入った方が使い勝手が良さそうな。 Erlang みたいに何でも Actor でやる言語ならともかく。 (edited)Task かな?Task ごとに Fault Isolation があるといいかも?init の中だと self.init と Self.init の両方がほぼ同じ意味で書けるけど、意味が違うことを今日知った (edited)extension CodableFromLosslessStringConvertible {
public init(from decoder: Decoder) throws {
let c = try decoder.singleValueContainer()
let string = try c.decode(String.self)
// ここが self.init だと怒られる
guard let value = Self.init(string) else {
throw DecodingError.dataCorruptedError(
in: c,
debugDescription: "invalid string: \(string)"
)
}
self = value
}
} (edited)self.init は戻り値がないからかな?self.init は 別のinitへの転送という意味なので。
しかもこの場合、throwsなinitから optional なinitを呼んでてそこの不一致もある。UIView とか UIViewController はパターン決まってるし、たまにクラスを継承して init 書くことあると戸惑う。 (edited)required init もありますからね。error as Any as? CustomStringConvertible で警告は消せた。 (edited)Swift.Error で受けたいんだよね"\(err)"にして薙ぎ払うとか?w (edited)CustomStringConvertible すら取れなかったときの最後の手段になってるswift-log を使うと、 Logger.Metadata ってのがあってrun 関数が標準ライブラリにあるとうれしい気がしてきた。
func run<T>(_ body: () -> T) -> T {
body()
}
よくあるプロパティの初期化が
var foo: Foo = {
...
return Foo(...)
}()
みたいなのも
var foo: Foo = run {
...
return Foo(...)
}
と書ける。 () でクロージャ式即実行の気持ち悪さが緩和されそう。
非同期版の
func run<T>(_ body: () async -> T) async -> T {
await body()
}
もあれば、 MainActor に戻す処理も
await { @MainActor in
self.foo = foo
}()
じゃなくて
await run { @MainActor in
self.foo = foo
}
と書ける。MainActor に戻す手段をどこかで見たなぁと思って WWDC のセッションや Proposal 漁ってたんですが、 { @MainActor in ... } を見つけて、これだったかも?ってなってました。T.self をデフォルトにするのおもしろいですね。 JSONDecoder.decode とかもこれやってほしいかも。
static func run<T>(resultType: T.Type = T.self, body: @MainActor @Sendable () throws -> T) async rethrows -> Timport Foundation
extension JSONDecoder {
func myDecode<T: Decodable>(_ type: T.Type = T.self, from data: Data) throws -> T {
try decode(type, from: data)
}
}
let decoded: [Int] = try! JSONDecoder().myDecode(from: "[2, 3, 5]".data(using: .utf8)!)
print(decoded)MainActor.run でいいのはなぜ?用途が異なるから?run はそもそも resultType がない場合は withXxx 系で多用されるパターンですよねInt? だった場合に、右辺が Int で推論されるのか Int? で推論されるのかが、 decode の場合は重い違いになってきます。T.self が与えられてるのはありかなぁと。JSONDecoder は具象型だから関係なくない? (edited)JSONDecoder.decode はたしかに。 KeyedContainerProtocol.decode(:for) の話かと思ってました。そっちのほうがたくさん書くのが大変だし。If each `KeyPath` encapsulates the type information, the `decode` methods won't need a `type` parameter.JSONDecoder だけの話じゃないか。class UICell {}
func _dequeue(_ type: UICell.Type) -> UICell {
print(type) // MyCellが出てこない
fatalError()
}
func dequeue<Cell: UICell>(_ type: UICell.Type = Cell.self) -> Cell {
_dequeue(Cell.self) as! Cell
}
class MyCell: UICell {}
class MyCell2: UICell {}
func cell(for row: Int) -> UICell {
let cell: UICell
if Bool.random() {
cell = dequeue(MyCell.self)
} else {
cell = dequeue(MyCell2.self)
}
return cell
}
cell(for: 0)
おぼろげな記憶から思い出してみたんですがこんな感じだったかも?func dequeue<Cell: UICell>(_ type: UICell.Type = Cell.self) -> Cell {
_dequeue(type) as! Cell
} (edited)-Ounchecked をdeprecatedにするって話があったと思うんですけど、いま調べ直したら特に確定的な事は出てこなくて、どうなったんでしたっけfunc main() {
let a: Int??? = 42
print(a as Any)
guard let a = a else { return }
print(a as Any)
guard let a = a else { return }
print(a as Any)
guard let a = a else { return }
print(a)
}
main()Optional(Optional(Optional(42)))
Optional(Optional(42))
Optional(42)
42-Ounchecked をdeprecatedにするって話があったと思うんですけど、いま調べ直したら特に確定的な事は出てこなくて、どうなったんでしたっけ -Ounchecked を取り除きたい・・・)-Ounchecked 自体はパフォーマンス追求するなら必要なんじゃないのかなぁ。分岐予測とかでほぼカバーできるにしても。ただ、 99% のケースでは不要。少なくとも AtCoder には要らない・・・。-remove-runtime-asserts などの指定があるので-O ファミリーである必要はないと思うんですよね。-Onone かつ -remove-runtime-asserts がユースケースとしてあり得るのかや、 assert が -O で消えることとの一貫性とか考えると最適化の一種じゃないのかなぁ。 (edited)-Osize はあり得ると思いますassert については -O で消える?消えない?-remove-runtime-asserts が assert ではなく precondition を消すためのものというのが明確だといいかなぁ。remove-runtime-asserts はassert を消すだけのものなのかしら? (edited)def RemoveRuntimeAsserts : Flag<["-"], "remove-runtime-asserts">,
Flags<[FrontendOption]>,
HelpText<"Remove runtime safety checks.">;-remove-safety-checks のほうがよくね?assert と precondition の名前は混乱していて、 Array のインデックスチェックは precondition ではなくインターナルななんとか assert 関数が呼ばれてたような気がする。precondition も広義の assert の一種なのでは。_precondition になってる。
@inlinable
@inline(__always)
internal func _checkValidSubscript(_ index: Int) {
_precondition(
(index >= 0) && (index < immutableCount),
"Index out of range"
)
}
https://github.com/apple/swift/blob/main/stdlib/public/core/ContiguousArrayBuffer.swift#L589-L596catch して適切なエラーに包んで投げるとか、ログを吐くとか。do 記法や try - catch がボイラープレート削減に寄与しないことがあるのはありえそう。guard ... catch { } みたいなのほしくなりそう。Optional では都度書くしかないから、それだったらエラーもそれでいいかなと。まとめてハンドリングできるケースなら do - catch したいですが。do - catch が活きますよね。do - catch が活きそう。guard let x = try foo() catch {
throw BarError(cause: error)
}let x: Foo
do {
x = try foo()
} catch {
throw BarError(cause: error)
}
になるのが辛くて・・・。try - catch を改良したとはいえ、↑のパターンは解決できてないので guard - try - catch がほしい。guard let x = try? foo() else {
throw BarError()
}
はできるけど cause がとれない。try - catch でボイラープレート削減ができないんじゃないかなと。func x() throws {
do {
try a()
} cathc {
throw XError.foo(cause: error)
}
do {
try b()
} cathc {
throw XError.bar(cause: error)
}
do {
try c()
} cathc {
throw XError.baz(cause: error)
}
}
みたいな。Result なら
func x() -> Result<X, XError> {
guard case .success(let a) = a() else {
return .failure(XError.foo)
}
guard case .success(let b) = b() else {
return .failure(XError.foo)
}
guard case .success(let c) = c() else {
return .failure(XError.foo)
}
return .success(.init(a, b, c))
}
みたいな場合には忘れることは起こらなくない?do - try - catch はあまり役に立たない。case success ってかいてるところがノイズだと思います。try - catch 要らなくない?って発想になるのかなと。guard let a = try a() catch { ... } がほしい。) (edited) try recover { try a() }
catch: { throw XError.foo(cause: $0) }guard - catch は良さそう。else の代わりに catch キーワードを使えるんですね。try でも Result でも変わらないようなコードってのはあって、その Result の劣化版として if のチェックでも対して困らないよって考えはまああり得るのかなと。try - catch や do 記法がなくていいということにはならないと思う。do 記法的なもの( try - catch を含む)があまり有効でない世界というのはあまり考えたことがなかったなと。do 記法と throws / try の話をしていたら、偶然だけど今日 inamiy さんが iOSDC で do 記法と async / await の話をしていた。
https://speakerdeck.com/inamiy/iosdc-japan-2021 public static subscript<EnclosingSelf: AnyObject>(
_enclosingInstance object: EnclosingSelf,
wrapped wrappedKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Value>,
storage storageKeyPath: ReferenceWritableKeyPath<EnclosingSelf, Published<Value>>
) -> Value {@_disfavoredOverload みたいに裏技使うから、SwiftUIのためにこっそり入ってたんかねPublished 使ってたらこれがstructなのに違和感を覚えて、色々と気になってきてOpenCombineを調べてみたら見つけたって感じですVStack {
Text("something")
#if os(iOS)
.iOSSpecificModifier()
#endif
.commonModifier()
}
がこうなりConsecutive statements on a line must be separated by a newlineエラーに
VStack {
Text("something")#if os(iOS)
.iOSSpecificModifier()
#endif
.commonModifier()
}JSON 型が標準で提供されると便利そう。自由なフォーマットの JSON をコード側で扱いたいとき。 JSONSerialization と比べるとパフォーマンス悪いけど。
enum JSON {
case number(Double)
case boolean(Bool)
case string(String)
case array([JSON])
case object([String: JSON])
case null
}
extension JSON: Codable {
init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
if let value = try? container.decode(Double.self) {
self = .number(value)
} else if let value = try? container.decode(Bool.self) {
self = .boolean(value)
} else if let value = try? container.decode(String.self) {
self = .string(value)
} else if let value = try? container.decode([JSON].self) {
self = .array(value)
} else if let value = try? container.decode([String: JSON].self) {
self = .object(value)
} else if container.decodeNil() {
self = .null
} else {
throw DecodingError.dataCorrupted(.init(codingPath: decoder.codingPath, debugDescription: "Failed to interpret as a JSON value.", underlyingError: nil))
}
}
func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
switch self {
case .number(let value):
try container.encode(value)
case .boolean(let value):
try container.encode(value)
case .string(let value):
try container.encode(value)
case .array(let value):
try container.encode(value)
case .object(let value):
try container.encode(value)
case .null:
try container.encodeNil()
}
}
}let json = "[true]".data(using: .utf8)!
let decoded = try JSONDecoder().decode(JSON.self, from: json) // .array(.boolean(true))Codable の仕組みの上で実現できないんですよね〜。Codable の仕組みを使いたいとか、 YAML に変換したいとか。Codable に適合しつつも、 JSONSerialization を使った高速なデコードが提供されてたらいいのかな。downloadTask の completion handler に渡される URL は
download(...) async throws -> (URL, URLResponse) の場合ってどうなるんでしょう? API リファレンスには何も書いていない。
https://developer.apple.com/documentation/foundation/urlsession/3767355-download
もし downloadTask と同じなら actor context の引き継ぎとかでキューに投入されてる間に消えてしまうし、そうでなければいつ削除されるんでしょう?downloadTask のときにどうやってファイルの read/write が衝突しないようにすればいいのかも微妙ですね。@escaping が小文字始まりなのに @Sendable が大文字始まりなの気持ち悪い気が。@sendable だったけど、 protocol Sendable と同じ意味なら @Sendable のほうがよくない?という話になった@ って Property Wrapper や Global Actor 等に限定されてたと思うのに、 @Sendable はそのルールを破ってる気がする。Sendable 以外のマーカープロトコルが導入された場合には @Sendable 相当のものが必要になると考えられ、そうするとプロコトル名に @ を付けるのは合理的だし、 Property Wrapper や Global Actor の @ が型名から生成されることとも一貫性があるのか。var a = 2
var b = 3
print(a, b)
(a, b) = (b, a)
print(a, b)var a = 2
var b = 3
print(a, b)
(a, b) = (b, a)
print(a, b) 2 3
3 2swap の方がいいだろうけど、これでも書けたのか。NSError の code ではなく、あえて _code を使っているコードを見かけたのですが、どんな意図が考えられますか?公開できるコードではないので貼れないですが・・・。NSError *error; error->_code;public protocol Error: Sendable {
var _domain: String { get }
var _code: Int { get }
// Note: _userInfo is always an NSDictionary, but we cannot use that type here
// because the standard library cannot depend on Foundation. However, the
// underscore implies that we control all implementations of this requirement.
var _userInfo: AnyObject? { get }
#if _runtime(_ObjC)
func _getEmbeddedNSError() -> AnyObject?
#endif
}Swift.Error って空じゃないんだ・・・NSError._code じゃなくて、Error._code が隠しパラメータとして存在していてNSError is Error だから、 NSError のじゃなくて Error の _code を見ているのかもError を NSError にしたときに Error の _code を code として使うのか。CustomNSError が用意されてるので違うような気もしますね/healthz を用意するかそこの設定を変える必要はあるかもしれません。let もできるといいよね。
guard let foo = try bar() catch { ... }let もできるといいよね。
guard let foo = try bar() catch { ... } guard let が Optional Binding 以外に使われるのは微妙だけど、これ提案したら通らないかなぁ・・・。guard let foo = try? bar() else { ... }
はできるけど、エラーが取れないんよね。guard let が Optional Binding 以外に使われるのは微妙だけど、これ提案したら通らないかなぁ・・・。 let foo: T
do { foo = try bar() } catch { ... }
で済むのであんまりメリットなさそうですけど,型名を省略できるというメリットならありそうですね. (edited)guard let foo = try bar() else catch {
switch error {
case let FooError as error: print(...)
default: print(...)
}
return
}
こんなイメージです。let foo: T
do { foo = try bar() }
catch let error as FooError { print(...); return }
catch { print(...); return }
let foo: T
switch Result(catching: { try bar() }) {
case .success(let value): foo = value
case .failure(let error as FooError): print(...); return
case .failure(let error): print(...); return
}do に catch を複数繋げられるの知りませんでした!
確かに初期化拒否すると脱出が強制されるのはそうですね。なるほど。let foo = true
let bar = true
outer: if foo {
if bar {
print("bar")
break outer
}
print("not bar")
}
print("end")let foo = true
let bar = true
outer: if foo {
if bar {
print("bar")
break outer
}
print("not bar")
}
print("end") bar
endhttps://swift.org
do {
print("OK")
} (edited)https://swift.org
do {
print("OK")
} (edited)OKDispatchQueue.main.async { [weak this = self] in
...
}
キャプチャにその場で名前つけられるっていうのも知らんかった。
ブラウザの古いタブを整理していて知らないTipsがいろいろ見つかった。DispatchQueue.main.async { [foo = self.foo, bar = self.bar] in
...
}
というのを典型的な利用例だと思うけどこの場合selfはキャプチャされない、でいいのかな?[foo, bar] と省略してかけます[foo = foo!] という感じになりますswift build とか swift test とかのようなXcodeプロジェクトが存在しない純粋なSwiftPMプロジェクトって、何か xcresult もしくはそれに準ずるビルド結果の出力ってあるのかな
1swift api-digester -sdk "$sdk" -dump-sdk -module "$module" \
-o "$output/$module.json" -I "$repodir/.build/debug"
これかな。
1_modify の気持ちを考えていると、yieldで渡ってきた値対して複数の操作をしたいとき、こういうのがstdlibに欲しくなる
func modify<T, ResultType>(_ x: inout T, _ body: (inout T) -> ResultType) -> ResultType {
return body(&x)
}// Before
var frame = controlStack.last!
self.valueStack.removeLast(valueStack.count - frame.height)
frame.unreachable = true
self.controlStack[controlStack.count - 1] = frame
// After
modify(&self.controlStack[controlStack.count - 1]) { frame in
self.valueStack.removeLast(valueStack.count - frame.height)
frame.unreachable = true
}@_optimize(none)
func blackhole<T>(_: T) {}
func modify<T, ResultType>(_ x: inout T, _ body: (inout T) -> ResultType) -> ResultType {
return body(&x)
}
struct Element {
var value1: Int64
var value2: Int64
var tails: [Int64]
}
func modifyElement(items: [Element]) {
var items = items
modify(&items[0]) { item in
item.value1 = 42
item.tails[0] = 50
}
blackhole(items)
}
import Foundation
let start = Date()
for _ in 0..<1000000 {
let baseItems = [
Element(value1: 1, value2: 2, tails: Array(repeating: 24, count: 3000)),
]
modifyElement(items: baseItems)
}
let elapsed = Date().timeIntervalSince(start)
print("took \(elapsed)") (edited)@_optimize(none)
func blackhole<T>(_: T) {}
func modify<T, ResultType>(_ x: inout T, _ body: (inout T) -> ResultType) -> ResultType {
return body(&x)
}
struct Element {
var value1: Int64
var value2: Int64
var tails: [Int64]
}
func modifyElement(items: [Element]) {
var items = items
modify(&items[0]) { item in
item.value1 = 42
item.tails[0] = 50
}
blackhole(items)
}
import Foundation
let start = Date()
for _ in 0..<1000000 {
let baseItems = [
Element(value1: 1, value2: 2, tails: Array(repeating: 24, count: 3000)),
]
modifyElement(items: baseItems)
}
let elapsed = Date().timeIntervalSince(start)
print("took \(elapsed)") (edited)took 2.2947229146957397 (edited)@_optimize(none)
func blackhole<T>(_: T) {}
struct Element {
var value1: Int64
var value2: Int64
var tails: [Int64]
}
func modifyElement(items: [Element]) {
var items = items
var item = items[0]
item.value1 = 42
item.tails[0] = 50
items[0] = item
blackhole(items)
}
import Foundation
let start = Date()
for _ in 0..<1000000 {
let baseItems = [
Element(value1: 1, value2: 2, tails: Array(repeating: 24, count: 3000)),
]
modifyElement(items: baseItems)
}
let elapsed = Date().timeIntervalSince(start)
print("took \(elapsed)") (edited)@_optimize(none)
func blackhole<T>(_: T) {}
struct Element {
var value1: Int64
var value2: Int64
var tails: [Int64]
}
func modifyElement(items: [Element]) {
var items = items
var item = items[0]
item.value1 = 42
item.tails[0] = 50
items[0] = item
blackhole(items)
}
import Foundation
let start = Date()
for _ in 0..<1000000 {
let baseItems = [
Element(value1: 1, value2: 2, tails: Array(repeating: 24, count: 3000)),
]
modifyElement(items: baseItems)
}
let elapsed = Date().timeIntervalSince(start)
print("took \(elapsed)") (edited)took 2.611519932746887 (edited)inout item = &array[index]
item.foo = a
item.bar = b
これが既定路線かな&mut っぽいarray には触れない?item が生きてる範囲では触れないendScope(item) を追加しようという話もあるTask は value: Success { get async throws } だけど Result は value: Success { get throws } にならないのかな Result.value ってもうありましたっけ?Result.get()typed throws 周りの議論で止まって?しまったんですね… (edited)ManagedCriticalStateというstructがあり、
https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/Locking.swift
用途としては、複数のactorとかqueueで状態を共有する場合や、前に他のスレッドで話にあったwithTaskCancellationHandlerのcancelHandlerで利用することが想定されているのですが、
https://github.com/apple/swift-async-algorithms/pull/7
actor内部の値にsyncにアクセスしたい場合にも使えるのかなと思ったのですが、どうなんでしょう?withCriticalRegion内部でawaitできないのでデータ競合は起きないのかなーと思ったのですが…
actor A {
let state = ManagedCriticalState(0)
nonisolated var value: Int {
state.withCriticalRegion {
$0
}
}
func update() {
state.withCriticalRegion {
$0 += 1
}
}
}
func test() async {
let a = A()
await a.update()
print(a.value) // 1
}
await test()ManagedCriticalStateというstructがあり、
https://github.com/apple/swift-async-algorithms/blob/main/Sources/AsyncAlgorithms/Locking.swift
用途としては、複数のactorとかqueueで状態を共有する場合や、前に他のスレッドで話にあったwithTaskCancellationHandlerのcancelHandlerで利用することが想定されているのですが、
https://github.com/apple/swift-async-algorithms/pull/7
actor内部の値にsyncにアクセスしたい場合にも使えるのかなと思ったのですが、どうなんでしょう?withCriticalRegion内部でawaitできないのでデータ競合は起きないのかなーと思ったのですが…
actor A {
let state = ManagedCriticalState(0)
nonisolated var value: Int {
state.withCriticalRegion {
$0
}
}
func update() {
state.withCriticalRegion {
$0 += 1
}
}
}
func test() async {
let a = A()
await a.update()
print(a.value) // 1
}
await test()
1func lazyMapCollection<C: Collection, T>(_ collection: C, body: @escaping (C.Element) -> T)
-> <R: Collection where R.Element == T> R {
return collection.lazy.map { body($0) }
}func lazyMapCollection<C: Collection, T>(_ collection: C, body: @escaping (C.Element) -> T)
-> <R: Collection where R.Element == T> R {
return collection.lazy.map { body($0) }
} struct S {}
func makePair() -> <T0> (T0, T0) {
(S(), S())
}// makePair()
sil hidden @$s1i8makePairQr_QrtyF : $@convention(thin) @substituted <τ_0_0, τ_0_1> () -> (@out τ_0_0, @out τ_0_1) for <@_opaqueReturnTypeOf("$s1i8makePairQr_QrtyF", 0) __, @_opaqueReturnTypeOf("$s1i8makePairQr_QrtyF", 0) __> {
...
}swift demangle '$s1i8makePairQr_QrtyF'
$s1i8makePairQr_QrtyF ---> i.makePair() -> (some, some)sil hidden @$s1i8makePairQr_QrtyF : $@convention(thin) @substituted <τ_0_0> () -> (@out τ_0_0, @out τ_0_0) for <@_opaqueReturnTypeOf("$s1i8makePairQr_QrtyF", 0) __, @_opaqueReturnTypeOf("$s1i8makePairQr_QrtyF", 0) __> {
こうなってほしいと*Sになってるんですよね
sil hidden @$s1a8makePairQr_QrtyF : $@convention(thin) @substituted <τ_0_0, τ_0_1> () -> (@out τ_0_0, @out τ_0_1) for <@_opaqueReturnTypeOf("$s1a8makePairQr_QrtyF", 0) __, @_opaqueReturnTypeOf("$s1a8makePairQr_QrtyF", 0) __> {
// %0 "$return_value" // user: %5
// %1 "$return_value" // user: %9
bb0(%0 : $*S, %1 : $*S): (edited)public func makePair1() -> <T0> (T0, T0) {
(S(), S())
}
public func makePair2() -> <T0, T1> (T0, T1) {
(S(), S())
}
// swiftinterface
public func makePair1() -> (T0, T0)
public func makePair2() -> (T0, T1)public func makePair1() -> <T0> (T0, T0) {
(S(), S())
}
public func makePair2() -> <T0, T1> (T0, T1) {
(S(), S())
}
// swiftinterface
public func makePair1() -> (T0, T0)
public func makePair2() -> (T0, T1) (T0, T1) な異なる型のペアを、 (T, T) な同一の型のペアとして渡すコードを書くと-> (some P, some P) とかは動くので謎@_opaqueReturnTypeOf ?public protocol P {}
public struct S: P {}
public func makePair() -> (some P, some P) {
(S(), S())
}// makePair()
sil hidden @$s1i8makePairQr_QrtyF : $@convention(thin) @substituted <τ_0_0, τ_0_1> () -> (@out τ_0_0, @out τ_0_1) for <@_opaqueReturnTypeOf("$s1i8makePairQr_QrtyF", 0) __, @_opaqueReturnTypeOf("$s1i8makePairQr_QrtyF", 0) __> {$ swift demangle '$s1i8makePairQr_QrtyF'
$s1i8makePairQr_QrtyF ---> i.makePair() -> (some, some)// .swiftinterface
public func makePair() -> (some i.P, some i.P)some が2つ返り値にあるから、これに0番、1番って番号が付いていて、swift_getTypeByMangledNameInContext で問い合わせる// makePair()
sil hidden @$s1i8makePairQr_QrtyF : $@convention(thin) @substituted <τ_0_0, τ_0_1> () -> (@out τ_0_0, @out τ_0_1) for <@_opaqueReturnTypeOf("$s1i8makePairQr_QrtyF", 0) __, @_opaqueReturnTypeOf("$s1i8makePairQr_QrtyF", 0) __> { // makePair()
sil @$s1b8makePairQr_QR_tyF : $@convention(thin) @substituted <τ_0_0, τ_0_1> () -> (@out τ_0_0, @out τ_0_1) for <@_opaqueReturnTypeOf("$s1b8makePairQr_QR_tyF", 0) __, @_opaqueReturnTypeOf("$s1b8makePairQr_QR_tyF", 1) __>(S(), S()) だからだと思う。public protocol P {}
public struct S1: P {}
public struct S2: P {}
public func makePair() -> (some P, some P) {
(S1(), S2())
}
// makePair()
sil @$s1i8makePairQr_QR_tyF : $@convention(thin) @substituted <τ_0_0, τ_0_1> () -> (@out τ_0_0, @out τ_0_1) for <@_opaqueReturnTypeOf("$s1i8makePairQr_QR_tyF", 0) __, @_opaqueReturnTypeOf("$s1i8makePairQr_QR_tyF", 1) __> { (edited)public protocol P {}
public struct S1: P {}
public struct S2: P {}
public func makePair() -> (some P, some P) {
(S1(), S1())
} (edited)public protocol P {}
public struct S1: P {}
public struct S2: P {}
public func makePair() -> (some P, some P) {
(S1(), S1())
} (edited)sil_stage canonical
import Builtin
import Swift
import SwiftShims
public protocol P {
}
public struct S1 : P {
init()
}
public struct S2 : P {
init()
}
public func makePair() -> (some P, some P)
// main
sil @main : $@convention(c) (Int32, UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>) -> Int32 {
bb0(%0 : $Int32, %1 : $UnsafeMutablePointer<Optional<UnsafeMutablePointer<Int8>>>):
%2 = integer_literal $Builtin.Int32, 0 // user: %3
%3 = struct $Int32 (%2 : $Builtin.Int32) // user: %4
return %3 : $Int32 // id: %4
} // end sil function 'main'
// S1.init()
sil hidden @$s4main2S1VACycfC : $@convention(method) (@thin S1.Type) -> S1 {
// %0 "$metatype"
bb0(%0 : $@thin S1.Type):
%1 = alloc_stack [lexical] $S1, var, name "self", implicit // user: %3
%2 = struct $S1 () // user: %4
dealloc_stack %1 : $*S1 // id: %3
return %2 : $S1 // id: %4
} // end sil function '$s4main2S1VACycfC'
// makePair()
sil @$s4main8makePairQr_QR_tyF : $@convention(thin) @substituted <τ_0_0, τ_0_1> () -> (@out τ_0_0, @out τ_0_1) for <@_opaqueReturnTypeOf("$s4main8makePairQr_QR_tyF", 0) __, @_opaqueReturnTypeOf("$s4main8makePairQr_QR_tyF", 1) __> {
// %0 "$return_value" // user: %5
// %1 "$return_value" // user: %9
bb0(%0 : $*S1, %1 : $*S1):
%2 = metatype $@thin S1.Type // user: %4
// function_ref S1.init()
%3 = function_ref @$s4main2S1VACycfC : $@convention(method) (@thin S1.Type) -> S1 // user: %4
%4 = apply %3(%2) : $@convention(method) (@thin S1.Type) -> S1 // user: %5
store %4 to %0 : $*S1 // id: %5
%6 = metatype $@thin S1.Type // user: %8
// function_ref S1.init()
%7 = function_ref @$s4main2S1VACycfC : $@convention(method) (@thin S1.Type) -> S1 // user: %8
%8 = apply %7(%6) : $@convention(m (edited)@_oRTOf(..., 1) になるswift_getTypeByMangledNameInContext は@__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo_MD")
@__swift_instantiateConcreteTypeFromMangledName({ i32, i32 }* @"$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD") (edited)__swift_instantiateConcreteTypeFromMangledName は swift_getTypeByMangledNameInContext をキャッシュ付きにラップするローカル関数なんだけどswift demangle '$s1e8ortTupleQr_QR_tyFQOyQo_MD'
$s1e8ortTupleQr_QR_tyFQOyQo_MD ---> demangling cache variable for type metadata for <<opaque return type of e.ortTuple() -> (some, some)>>.0opaque return type [0] をピンポイント問い合わせしていて$s1e8ortTupleQr_QR_tyFQOyQo__AaBQr_QR_tyFQOyQo0_tMD ---> demangling cache variable for type metadata for (<<opaque return type of e.ortTuple() -> (some, some)>>.0, <<opaque return type of e.ortTuple() -> (some, some)>>.1)(ort[0], ort[1]) っていうマングリングでkind=Global
kind=TypeMetadataDemanglingCache
kind=Type
kind=Tuple
kind=TupleElement
kind=Type
kind=OpaqueType
kind=OpaqueReturnTypeOf
kind=Function
kind=Module, text="e"
kind=Identifier, text="ortTuple"
kind=Type
kind=FunctionType
kind=ArgumentTuple
kind=Type
kind=Tuple
kind=ReturnType
kind=Type
kind=Tuple
kind=TupleElement
kind=Type
kind=OpaqueReturnType
kind=TupleElement
kind=Type
kind=OpaqueReturnTypeIndexed, index=0
kind=Index, index=0
kind=TypeList
kind=TypeList
kind=TupleElement
kind=Type
kind=OpaqueType
kind=OpaqueReturnTypeOf
kind=Function
kind=Module, text="e"
kind=Identifier, text="ortTuple"
kind=Type
kind=FunctionType
kind=ArgumentTuple
kind=Type
kind=Tuple
kind=ReturnType
kind=Type
kind=Tuple
kind=TupleElement
kind=Type
kind=OpaqueReturnType
kind=TupleElement
kind=Type
kind=OpaqueReturnTypeIndexed, index=0
kind=Index, index=1
kind=TypeList
kind=TypeList(ort[0], ort[1]) って式が書いてあるort って書くところでopaque return type of ( function, index ) (ortOf( foo: returns (some some) , 0 ), ortOf ( foo: returns (some some), 1 ) )-> <T0, T1> (T0, T1) でも -> <T0> (T0, T0) でも-> (some, some) になっててortOf で指定できるindexは 0と1 が対応づいていて<T0, T1> なのか <T0> なのか、もしくは 2つ目が <T0, T1 where T1 == T0> になるのかはわからんけど、ortOf のindexの対応関係は、
ソースレベルのシグネチャから、IRレベルのシグネチャを対応させてる関係上、
caller側でもcallee側のコンパイル時と同じようにわかるはずだし。public protocol P<A> {
associatedtype A
}
struct S1<A>: P {}
struct S2<A>: P {}
public func makeP() -> <T: P, U: P where T.A == U.A> (T, U) {
return (S1<Int>(), S2<Int>())
}// swift-interface-format-version: 1.0
// swift-compiler-version: Apple Swift version 5.8-dev (LLVM 515f8ef5b9ec986, Swift 7435c936a6a67d0)
// swift-module-flags: -target x86_64-apple-macosx12.0 -enable-objc-interop -module-name i
import Swift
import _Concurrency
#if compiler(>=5.3) && $PrimaryAssociatedTypes2
public protocol P<A> {
associatedtype A
}
#else
public protocol P {
associatedtype A
}
#endif
public func makeP() -> (T, U)any Sequence って self-conform してるんですっけ?
@swift-5.7.1-dev
struct Foo {}
protocol Bar {
associatedtype Foos: Sequence where Foos.Element == Foo
var foos: Foos { get }
}
struct Baz: Bar {
var foos: [Foo] { [Foo()] }
}
let bar: any Bar = Baz()
for foo in bar.foos as any Sequence {
print(foo)
}any Sequence って self-conform してるんですっけ?
@swift-5.7.1-dev
struct Foo {}
protocol Bar {
associatedtype Foos: Sequence where Foos.Element == Foo
var foos: Foos { get }
}
struct Baz: Bar {
var foos: [Foo] { [Foo()] }
}
let bar: any Bar = Baz()
for foo in bar.foos as any Sequence {
print(foo)
} Foo()someにするかどうかという議論が最近盛り上がってますね(やるべきなのか、やるとしたらいつどうやるのか)
これまで存在型になって問題が起きる可能性があったのでanyが入ったという動機を考えるとそうなるのかなあとは思いましたが、どうなんでしょう?
https://forums.swift.org/t/discussion-eliding-some-in-swift-6/57918 (edited)some or any doesn't really affect the domain of a function, particularly for non-inout function arguments. With the recent additions to generalize existentials and allow for implicit opening, func foo(_: some P) and func foo(_: any P) both accept the same sets of parameters and have the same sets of capabilities operating on their arguments, but func foo(_: some P) is slightly more efficient as public ABI because it can accept a conforming value as-is without boxing it, and also more flexible by default inside the body of foo, since you can use all of P's methods on it without an opening step. It would make sense to favor the more efficient, more expressive interpretation of func foo(_: P) to mean func foo(_: some P), independent of what we choose to do in places where there's an effective semantic difference.
func foo(_: P) を func foo(_: some P) にするとして、 func foo(_: [P]) は func foo(_: [some P]) になるのかな?それはまた違う気が・・・。[P]に異なる型を入れようとした場合コンパイラがエラーにするので、既存のコードを壊すことはないから大丈夫、必要ならanyを付ける、とかなんですかね???func foo(_: [some P]) (func foo<T: P>(_: [T]))とfunc foo(_: [any P]) は全然シグネチャが違うので変なところで呼び出し優先順位が入れ替わったりしちゃわないかなぁ
1I also think taking this approach will lead to a confusing model because programmers will need to deeply understand where they can omit some and where they cannot. For example, you'd be able to write a parameter of type P, but not of type [P].Int.self と \Int.self など)が対応してないから。
Int.self
Int.Type.self
\Int.self
\Int.Type.selfInt.self // Int.Type
Int.Type.self // Int.Type.Type
\Int.self // WritableKeyPath<Int, Int>
\Int.Type.self // WritableKeyPath<Int.Type, Int.Type>
ややこしいTypeになる。
後半はプロパティとかと同じでselfが指すものを対象とするKeyPathになる.Int.self は Int.Type のインスタンスだけど、 \Int.self は Int.Type ではなく Int (から Int へ)の KeyPath になり、 Int.Type の KeyPath は \Int.Type.self と書かないといけないけど、 Int.Type.self は Int.Type.Type のインスタンスというわかりづらさ。 (edited)extension Int {
static var mySelf: Int.Type = Int.self
var mySelf: Int { self }
}
print(type(of: Int.mySelf))
print(type(of: \Int.mySelf))extension Int {
static var mySelf: Int.Type = Int.self
var mySelf: Int { self }
}
print(type(of: Int.mySelf))
print(type(of: \Int.mySelf)) Int.Type
KeyPath<Int, Int>print(Int.self[keyPath: \Int.Type.self])@available(*, unavailable)
extension ISO8601DateFormatter : @unchecked Sendable {
}
たまたまこういうの見つけたんですが、これってSendableじゃないことを明示的に定義している?extension ISO8601DateFormatter: @unchecked Sendable {} 書いたら上書きできるな。これ書くことにどういう意味があるんだろうTSCBasic.Thread と Foundation.Thread のどちらも同じ優先度だけど、initの引数にとるクロージャが Sendable かどうかでオーバーロード優先順位がFoundationに寄った?struct S {
var _value: Int = 0
var value: Int {
get {
print("get")
return _value
}
set {
print("set")
_value = newValue
}
}
}
var s = S()
s[keyPath: \.value] = 42struct S {
var _value: Int = 0
var value: Int {
get {
print("get")
return _value
}
set {
print("set")
_value = newValue
}
}
}
var s = S()
s[keyPath: \.value] = 42 get
setWritableKeyPath 経由で書き込みするときってgetter呼ばれるんですねstruct S {
var _value: Int = 0
var value: Int {
get {
print("get")
return _value
}
set {
print("set")
_value = newValue
}
}
}
var s = S()
s[keyPath: \.value] = 42struct S {
var _value: Int = 0
var value: Int {
get {
print("get")
return _value
}
set {
print("set")
_value = newValue
}
}
}
var s = S()
s[keyPath: \.value] = 42 set@LateInit みたいなpropertyWrapperでこれに遭遇してちょっと困ったんですよねs.foo.bar = x みたいなアクセスだと、fooをgetしてbarの位置にx書き込んでfooに書き戻すんですけどMutatingWritebackBuffer が書き戻す君